patch-2.4.22 linux-2.4.22/drivers/acpi/tables/tbconvrt.c
Next file: linux-2.4.22/drivers/acpi/tables/tbget.c
Previous file: linux-2.4.22/drivers/acpi/tables/Makefile
Back to the patch index
Back to the overall index
- Lines: 901
- Date:
2003-08-25 04:44:41.000000000 -0700
- Orig file:
linux-2.4.21/drivers/acpi/tables/tbconvrt.c
- Orig date:
2001-10-24 14:06:22.000000000 -0700
diff -urN linux-2.4.21/drivers/acpi/tables/tbconvrt.c linux-2.4.22/drivers/acpi/tables/tbconvrt.c
@@ -1,71 +1,84 @@
/******************************************************************************
*
* Module Name: tbconvrt - ACPI Table conversion utilities
- * $Revision: 28 $
*
*****************************************************************************/
/*
- * 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 "actables.h"
-#include "actbl.h"
+#include <acpi/acpi.h>
+#include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES
- MODULE_NAME ("tbconvrt")
+ ACPI_MODULE_NAME ("tbconvrt")
/*******************************************************************************
*
- * FUNCTION: Acpi_tb_get_table_count
+ * FUNCTION: acpi_tb_get_table_count
*
- * PARAMETERS:
+ * PARAMETERS: RSDP - Pointer to the RSDP
+ * RSDT - Pointer to the RSDT/XSDT
*
- * RETURN:
+ * RETURN: The number of tables pointed to by the RSDT or XSDT.
*
- * DESCRIPTION: Calculate the number of tables
+ * DESCRIPTION: Calculate the number of tables. Automatically handles either
+ * an RSDT or XSDT.
*
******************************************************************************/
u32
acpi_tb_get_table_count (
- RSDP_DESCRIPTOR *RSDP,
- acpi_table_header *RSDT)
+ struct rsdp_descriptor *RSDP,
+ struct acpi_table_header *RSDT)
{
- u32 pointer_size;
+ u32 pointer_size;
- FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY ();
-#ifndef _IA64
-
if (RSDP->revision < 2) {
pointer_size = sizeof (u32);
}
-
- else
-#endif
- {
+ else {
pointer_size = sizeof (u64);
}
@@ -75,17 +88,17 @@
* pointers contained within the RSDT/XSDT. The size of the pointers
* is architecture-dependent.
*/
- return ((RSDT->length - sizeof (acpi_table_header)) / pointer_size);
+ return ((RSDT->length - sizeof (struct acpi_table_header)) / pointer_size);
}
/*******************************************************************************
*
- * FUNCTION: Acpi_tb_convert_to_xsdt
+ * FUNCTION: acpi_tb_convert_to_xsdt
*
- * PARAMETERS:
+ * PARAMETERS: table_info - Info about the RSDT
*
- * RETURN:
+ * RETURN: Status
*
* DESCRIPTION: Convert an RSDT to an XSDT (internal common format)
*
@@ -93,24 +106,20 @@
acpi_status
acpi_tb_convert_to_xsdt (
- acpi_table_desc *table_info,
- u32 *number_of_tables)
+ struct acpi_table_desc *table_info)
{
- u32 table_size;
- u32 i;
- xsdt_descriptor *new_table;
-
-
- FUNCTION_ENTRY ();
+ acpi_size table_size;
+ u32 i;
+ XSDT_DESCRIPTOR *new_table;
- *number_of_tables = acpi_tb_get_table_count (acpi_gbl_RSDP, table_info->pointer);
+ ACPI_FUNCTION_ENTRY ();
/* Compute size of the converted XSDT */
- table_size = (*number_of_tables * sizeof (u64)) + sizeof (acpi_table_header);
-
+ table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof (u64)) +
+ sizeof (struct acpi_table_header);
/* Allocate an XSDT */
@@ -121,37 +130,29 @@
/* Copy the header and set the length */
- MEMCPY (new_table, table_info->pointer, sizeof (acpi_table_header));
- new_table->header.length = table_size;
+ ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header));
+ new_table->header.length = (u32) table_size;
/* Copy the table pointers */
- for (i = 0; i < *number_of_tables; i++) {
+ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
if (acpi_gbl_RSDP->revision < 2) {
-#ifdef _IA64
- new_table->table_offset_entry[i] =
- ((RSDT_DESCRIPTOR_REV071 *) table_info->pointer)->table_offset_entry[i];
-#else
ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
- ((RSDT_DESCRIPTOR_REV1 *) table_info->pointer)->table_offset_entry[i]);
-#endif
+ ((struct rsdt_descriptor_rev1 *) table_info->pointer)->table_offset_entry[i]);
}
else {
new_table->table_offset_entry[i] =
- ((xsdt_descriptor *) table_info->pointer)->table_offset_entry[i];
+ ((XSDT_DESCRIPTOR *) table_info->pointer)->table_offset_entry[i];
}
}
-
/* Delete the original table (either mapped or in a buffer) */
acpi_tb_delete_single_table (table_info);
-
/* Point the table descriptor to the new table */
- table_info->pointer = (acpi_table_header *) new_table;
- table_info->base_pointer = (acpi_table_header *) new_table;
+ table_info->pointer = (struct acpi_table_header *) new_table;
table_info->length = table_size;
table_info->allocation = ACPI_MEM_ALLOCATED;
@@ -159,327 +160,325 @@
}
-/*******************************************************************************
+/******************************************************************************
*
- * FUNCTION: Acpi_tb_convert_table_fadt
+ * FUNCTION: acpi_tb_init_generic_address
*
- * PARAMETERS:
+ * PARAMETERS: new_gas_struct - GAS struct to be initialized
+ * register_bit_width - Width of this register
+ * Address - Address of the register
*
- * RETURN:
+ * RETURN: None
*
- * DESCRIPTION:
- * Converts BIOS supplied 1.0 and 0.71 ACPI FADT to an intermediate
- * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
- * copied to the intermediate FADT. The ACPI CA software uses this
- * intermediate FADT. Thus a significant amount of special #ifdef
- * type codeing is saved. This intermediate FADT will need to be
- * freed at some point.
+ * DESCRIPTION: Initialize a GAS structure.
*
******************************************************************************/
-acpi_status
-acpi_tb_convert_table_fadt (void)
+static void
+acpi_tb_init_generic_address (
+ struct acpi_generic_address *new_gas_struct,
+ u8 register_bit_width,
+ acpi_physical_address address)
{
-#ifdef _IA64
- fadt_descriptor_rev071 *FADT71;
- u8 pm1_address_space;
- u8 pm2_address_space;
- u8 pm_timer_address_space;
- u8 gpe0address_space;
- u8 gpe1_address_space;
-#else
- fadt_descriptor_rev1 *FADT1;
-#endif
-
- fadt_descriptor_rev2 *FADT2;
- acpi_table_desc *table_desc;
-
-
- FUNCTION_TRACE ("Tb_convert_table_fadt");
-
-
- /* Acpi_gbl_FADT is valid */
- /* Allocate and zero the 2.0 buffer */
-
- FADT2 = ACPI_MEM_CALLOCATE (sizeof (fadt_descriptor_rev2));
- if (FADT2 == NULL) {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
-
- /* The ACPI FADT revision number is FADT2_REVISION_ID=3 */
- /* So, if the current table revision is less than 3 it is type 1.0 or 0.71 */
-
- if (acpi_gbl_FADT->header.revision >= FADT2_REVISION_ID) {
- /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
-
- *FADT2 = *((fadt_descriptor_rev2*) acpi_gbl_FADT);
-
- }
-
- else {
-
-#ifdef _IA64
- /*
- * For the 64-bit case only, a revision ID less than V2.0 means the
- * tables are the 0.71 extensions
- */
-
- /* The BIOS stored FADT should agree with Revision 0.71 */
-
- FADT71 = (fadt_descriptor_rev071 *) acpi_gbl_FADT;
-
- /* Copy the table header*/
+ ACPI_STORE_ADDRESS (new_gas_struct->address, address);
- FADT2->header = FADT71->header;
-
- /* Copy the common fields */
-
- FADT2->sci_int = FADT71->sci_int;
- FADT2->acpi_enable = FADT71->acpi_enable;
- FADT2->acpi_disable = FADT71->acpi_disable;
- FADT2->S4bios_req = FADT71->S4bios_req;
- FADT2->plvl2_lat = FADT71->plvl2_lat;
- FADT2->plvl3_lat = FADT71->plvl3_lat;
- FADT2->day_alrm = FADT71->day_alrm;
- FADT2->mon_alrm = FADT71->mon_alrm;
- FADT2->century = FADT71->century;
- FADT2->gpe1_base = FADT71->gpe1_base;
-
- /*
- * We still use the block length registers even though
- * the GAS structure should obsolete them. This is because
- * these registers are byte lengths versus the GAS which
- * contains a bit width
- */
- FADT2->pm1_evt_len = FADT71->pm1_evt_len;
- FADT2->pm1_cnt_len = FADT71->pm1_cnt_len;
- FADT2->pm2_cnt_len = FADT71->pm2_cnt_len;
- FADT2->pm_tm_len = FADT71->pm_tm_len;
- FADT2->gpe0blk_len = FADT71->gpe0blk_len;
- FADT2->gpe1_blk_len = FADT71->gpe1_blk_len;
- FADT2->gpe1_base = FADT71->gpe1_base;
-
- /* Copy the existing 0.71 flags to 2.0. The other bits are zero.*/
-
- FADT2->wb_invd = FADT71->flush_cash;
- FADT2->proc_c1 = FADT71->proc_c1;
- FADT2->plvl2_up = FADT71->plvl2_up;
- FADT2->pwr_button = FADT71->pwr_button;
- FADT2->sleep_button = FADT71->sleep_button;
- FADT2->fixed_rTC = FADT71->fixed_rTC;
- FADT2->rtcs4 = FADT71->rtcs4;
- FADT2->tmr_val_ext = FADT71->tmr_val_ext;
- FADT2->dock_cap = FADT71->dock_cap;
-
-
- /* We should not use these next two addresses */
- /* Since our buffer is pre-zeroed nothing to do for */
- /* the next three data items in the structure */
- /* FADT2->Firmware_ctrl = 0; */
- /* FADT2->Dsdt = 0; */
-
- /* System Interrupt Model isn't used in ACPI 2.0*/
- /* FADT2->Reserved1 = 0; */
-
- /* This field is set by the OEM to convey the preferred */
- /* power management profile to OSPM. It doesn't have any*/
- /* 0.71 equivalence. Since we don't know what kind of */
- /* 64-bit system this is, we will pick unspecified. */
-
- FADT2->prefer_PM_profile = PM_UNSPECIFIED;
-
-
- /* Port address of SMI command port */
- /* We shouldn't use this port because IA64 doesn't */
- /* have or use SMI. It has PMI. */
+ new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+ new_gas_struct->register_bit_width = register_bit_width;
+ new_gas_struct->register_bit_offset = 0;
+ new_gas_struct->reserved = 0;
+}
- FADT2->smi_cmd = (u32)(FADT71->smi_cmd & 0xFFFFFFFF);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_convert_fadt1
+ *
+ * PARAMETERS: local_fadt - Pointer to new FADT
+ * original_fadt - Pointer to old FADT
+ *
+ * RETURN: Populates local_fadt
+ *
+ * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format
+ *
+ ******************************************************************************/
- /* processor performance state control*/
- /* The value OSPM writes to the SMI_CMD register to assume */
- /* processor performance state control responsibility. */
- /* There isn't any equivalence in 0.71 */
- /* Again this should be meaningless for IA64 */
- /* FADT2->Pstate_cnt = 0; */
+static void
+acpi_tb_convert_fadt1 (
+ struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev1 *original_fadt)
+{
- /* The 32-bit Power management and GPE registers are */
- /* not valid in IA-64 and we are not going to use them */
- /* so leaving them pre-zeroed. */
- /* Support for the _CST object and C States change notification.*/
- /* This data item hasn't any 0.71 equivalence so leaving it zero.*/
- /* FADT2->Cst_cnt = 0; */
+ /* ACPI 1.0 FACS */
+ /* The BIOS stored FADT should agree with Revision 1.0 */
- /* number of flush strides that need to be read */
- /* No 0.71 equivalence. Leave pre-zeroed. */
- /* FADT2->Flush_size = 0; */
+ /*
+ * Copy the table header and the common part of the tables.
+ *
+ * The 2.0 table is an extension of the 1.0 table, so the entire 1.0
+ * table can be copied first, then expand some fields to 64 bits.
+ */
+ ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev1));
- /* Processor's memory cache line width, in bytes */
- /* No 0.71 equivalence. Leave pre-zeroed. */
- /* FADT2->Flush_stride = 0; */
+ /* Convert table pointers to 64-bit fields */
- /* Processor's duty cycle index in processor's P_CNT reg*/
- /* No 0.71 equivalence. Leave pre-zeroed. */
- /* FADT2->Duty_offset = 0; */
+ ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
+ ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
- /* Processor's duty cycle value bit width in P_CNT register.*/
- /* No 0.71 equivalence. Leave pre-zeroed. */
- /* FADT2->Duty_width = 0; */
+ /*
+ * System Interrupt Model isn't used in ACPI 2.0 (local_fadt->Reserved1 = 0;)
+ */
+ /*
+ * This field is set by the OEM to convey the preferred power management
+ * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't
+ * know what kind of 32-bit system this is, we will use "unspecified".
+ */
+ local_fadt->prefer_PM_profile = PM_UNSPECIFIED;
- /* Since there isn't any equivalence in 0.71 */
- /* and since Big_sur had to support legacy */
+ /*
+ * Processor Performance State Control. This is the value OSPM writes to
+ * the SMI_CMD register to assume processor performance state control
+ * responsibility. There isn't any equivalence in 1.0, leave it zeroed.
+ */
+ local_fadt->pstate_cnt = 0;
- FADT2->iapc_boot_arch = BAF_LEGACY_DEVICES;
+ /*
+ * Support for the _CST object and C States change notification.
+ * This data item hasn't any 1.0 equivalence so leave it zero.
+ */
+ local_fadt->cst_cnt = 0;
- /* Copy to ACPI 2.0 64-BIT Extended Addresses */
+ /*
+ * Since there isn't any equivalence in 1.0 and since it highly likely
+ * that a 1.0 system has legacy support.
+ */
+ local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES;
- FADT2->Xfirmware_ctrl = FADT71->firmware_ctrl;
- FADT2->Xdsdt = FADT71->dsdt;
+ /*
+ * Convert the V1.0 block addresses to V2.0 GAS structures
+ */
+ acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len,
+ (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
+ acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len,
+ (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
+ acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len,
+ (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
+ acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len,
+ (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
+ acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len,
+ (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
+ acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len,
+ (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
+ acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0,
+ (acpi_physical_address) local_fadt->V1_gpe0_blk);
+ acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0,
+ (acpi_physical_address) local_fadt->V1_gpe1_blk);
+
+ /* Create separate GAS structs for the PM1 Enable registers */
+
+ acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
+ (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
+ (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address +
+ ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+
+ /* PM1B is optional; leave null if not present */
+
+ if (local_fadt->xpm1b_evt_blk.address) {
+ acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
+ (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
+ (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address +
+ ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ }
+}
- /* Extract the address space IDs */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_convert_fadt2
+ *
+ * PARAMETERS: local_fadt - Pointer to new FADT
+ * original_fadt - Pointer to old FADT
+ *
+ * RETURN: Populates local_fadt
+ *
+ * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format.
+ * Handles optional "X" fields.
+ *
+ ******************************************************************************/
- pm1_address_space = (u8)((FADT71->address_space & PM1_BLK_ADDRESS_SPACE) >> 1);
- pm2_address_space = (u8)((FADT71->address_space & PM2_CNT_BLK_ADDRESS_SPACE) >> 2);
- pm_timer_address_space = (u8)((FADT71->address_space & PM_TMR_BLK_ADDRESS_SPACE) >> 3);
- gpe0address_space = (u8)((FADT71->address_space & GPE0_BLK_ADDRESS_SPACE) >> 4);
- gpe1_address_space = (u8)((FADT71->address_space & GPE1_BLK_ADDRESS_SPACE) >> 5);
+static void
+acpi_tb_convert_fadt2 (
+ struct fadt_descriptor_rev2 *local_fadt,
+ struct fadt_descriptor_rev2 *original_fadt)
+{
- /*
- * Convert the 0.71 (non-GAS style) Block addresses to V2.0 GAS structures,
- * in this order:
- *
- * PM 1_a Events
- * PM 1_b Events
- * PM 1_a Control
- * PM 1_b Control
- * PM 2 Control
- * PM Timer Control
- * GPE Block 0
- * GPE Block 1
- */
+ /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1a_evt_blk, FADT71->pm1_evt_len, FADT71->pm1a_evt_blk, pm1_address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1b_evt_blk, FADT71->pm1_evt_len, FADT71->pm1b_evt_blk, pm1_address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1a_cnt_blk, FADT71->pm1_cnt_len, FADT71->pm1a_cnt_blk, pm1_address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1b_cnt_blk, FADT71->pm1_cnt_len, FADT71->pm1b_cnt_blk, pm1_address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm2_cnt_blk, FADT71->pm2_cnt_len, FADT71->pm2_cnt_blk, pm2_address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm_tmr_blk, FADT71->pm_tm_len, FADT71->pm_tmr_blk, pm_timer_address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xgpe0blk, FADT71->gpe0blk_len, FADT71->gpe0blk, gpe0address_space);
- ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xgpe1_blk, FADT71->gpe1_blk_len, FADT71->gpe1_blk, gpe1_address_space);
+ ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev2));
-#else
+ /*
+ * "X" fields are optional extensions to the original V1.0 fields, so
+ * we must selectively expand V1.0 fields if the corresponding X field
+ * is zero.
+ */
+ if (!(local_fadt->xfirmware_ctrl)) {
+ ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl);
+ }
- /* ACPI 1.0 FACS */
+ if (!(local_fadt->Xdsdt)) {
+ ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt);
+ }
+ if (!(local_fadt->xpm1a_evt_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk,
+ local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1a_evt_blk);
+ }
- /* The BIOS stored FADT should agree with Revision 1.0 */
+ if (!(local_fadt->xpm1b_evt_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk,
+ local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1b_evt_blk);
+ }
- FADT1 = (fadt_descriptor_rev1*) acpi_gbl_FADT;
+ if (!(local_fadt->xpm1a_cnt_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk,
+ local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk);
+ }
- /*
- * Copy the table header and the common part of the tables
- * The 2.0 table is an extension of the 1.0 table, so the
- * entire 1.0 table can be copied first, then expand some
- * fields to 64 bits.
- */
- MEMCPY (FADT2, FADT1, sizeof (fadt_descriptor_rev1));
+ if (!(local_fadt->xpm1b_cnt_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk,
+ local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk);
+ }
+ if (!(local_fadt->xpm2_cnt_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk,
+ local_fadt->pm2_cnt_len, (acpi_physical_address) local_fadt->V1_pm2_cnt_blk);
+ }
- /* Convert table pointers to 64-bit fields */
+ if (!(local_fadt->xpm_tmr_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk,
+ local_fadt->pm_tm_len, (acpi_physical_address) local_fadt->V1_pm_tmr_blk);
+ }
- ACPI_STORE_ADDRESS (FADT2->Xfirmware_ctrl, FADT1->firmware_ctrl);
- ACPI_STORE_ADDRESS (FADT2->Xdsdt, FADT1->dsdt);
+ if (!(local_fadt->xgpe0_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xgpe0_blk,
+ 0, (acpi_physical_address) local_fadt->V1_gpe0_blk);
+ }
- /* System Interrupt Model isn't used in ACPI 2.0*/
- /* FADT2->Reserved1 = 0; */
+ if (!(local_fadt->xgpe1_blk.address)) {
+ acpi_tb_init_generic_address (&local_fadt->xgpe1_blk,
+ 0, (acpi_physical_address) local_fadt->V1_gpe1_blk);
+ }
- /* This field is set by the OEM to convey the preferred */
- /* power management profile to OSPM. It doesn't have any*/
- /* 1.0 equivalence. Since we don't know what kind of */
- /* 32-bit system this is, we will pick unspecified. */
+ /* Create separate GAS structs for the PM1 Enable registers */
- FADT2->prefer_PM_profile = PM_UNSPECIFIED;
+ acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable,
+ (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
+ (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address +
+ ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_gbl_xpm1a_enable.address_space_id = local_fadt->xpm1a_evt_blk.address_space_id;
+
+ /* PM1B is optional; leave null if not present */
+
+ if (local_fadt->xpm1b_evt_blk.address) {
+ acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable,
+ (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len),
+ (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address +
+ ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len)));
+ acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id;
+ }
+}
- /* Processor Performance State Control. This is the value */
- /* OSPM writes to the SMI_CMD register to assume processor */
- /* performance state control responsibility. There isn't */
- /* any equivalence in 1.0. So leave it zeroed. */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_convert_table_fadt
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
+ * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
+ * copied to the local FADT. The ACPI CA software uses this
+ * local FADT. Thus a significant amount of special #ifdef
+ * type codeing is saved.
+ *
+ ******************************************************************************/
- FADT2->pstate_cnt = 0;
+acpi_status
+acpi_tb_convert_table_fadt (void)
+{
+ struct fadt_descriptor_rev2 *local_fadt;
+ struct acpi_table_desc *table_desc;
- /* Support for the _CST object and C States change notification.*/
- /* This data item hasn't any 1.0 equivalence so leaving it zero.*/
+ ACPI_FUNCTION_TRACE ("tb_convert_table_fadt");
- FADT2->cst_cnt = 0;
+ /*
+ * acpi_gbl_FADT is valid
+ * Allocate and zero the 2.0 FADT buffer
+ */
+ local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2));
+ if (local_fadt == NULL) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
- /* Since there isn't any equivalence in 1.0 and since it */
- /* is highly likely that a 1.0 system has legacy support. */
+ /*
+ * FADT length and version validation. The table must be at least as
+ * long as the version 1.0 FADT
+ */
+ if (acpi_gbl_FADT->header.length < sizeof (struct fadt_descriptor_rev1)) {
+ ACPI_REPORT_ERROR (("Invalid FADT table length: 0x%X\n", acpi_gbl_FADT->header.length));
+ return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
+ }
- FADT2->iapc_boot_arch = BAF_LEGACY_DEVICES;
+ if (acpi_gbl_FADT->header.revision >= FADT2_REVISION_ID) {
+ if (acpi_gbl_FADT->header.length < sizeof (struct fadt_descriptor_rev2)) {
+ /* Length is too short to be a V2.0 table */
+ ACPI_REPORT_WARNING (("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n",
+ acpi_gbl_FADT->header.length, acpi_gbl_FADT->header.revision));
- /*
- * Convert the V1.0 Block addresses to V2.0 GAS structures
- * in this order:
- *
- * PM 1_a Events
- * PM 1_b Events
- * PM 1_a Control
- * PM 1_b Control
- * PM 2 Control
- * PM Timer Control
- * GPE Block 0
- * GPE Block 1
- */
+ acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
+ }
+ else {
+ /* Valid V2.0 table */
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1a_evt_blk, FADT1->pm1_evt_len, FADT1->pm1a_evt_blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1b_evt_blk, FADT1->pm1_evt_len, FADT1->pm1b_evt_blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1a_cnt_blk, FADT1->pm1_cnt_len, FADT1->pm1a_cnt_blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1b_cnt_blk, FADT1->pm1_cnt_len, FADT1->pm1b_cnt_blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm2_cnt_blk, FADT1->pm2_cnt_len, FADT1->pm2_cnt_blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm_tmr_blk, FADT1->pm_tm_len, FADT1->pm_tmr_blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xgpe0blk, FADT1->gpe0blk_len, FADT1->gpe0blk);
- ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xgpe1_blk, FADT1->gpe1_blk_len, FADT1->gpe1_blk);
-#endif
+ acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT);
+ }
}
+ else {
+ /* Valid V1.0 table */
+ acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT);
+ }
/*
- * Global FADT pointer will point to the common V2.0 FADT
+ * Global FADT pointer will point to the new common V2.0 FADT
*/
- acpi_gbl_FADT = FADT2;
+ acpi_gbl_FADT = local_fadt;
acpi_gbl_FADT->header.length = sizeof (FADT_DESCRIPTOR);
-
/* Free the original table */
- table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_FADT];
+ table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
acpi_tb_delete_single_table (table_desc);
-
/* Install the new table */
- table_desc->pointer = (acpi_table_header *) acpi_gbl_FADT;
- table_desc->base_pointer = acpi_gbl_FADT;
- table_desc->allocation = ACPI_MEM_ALLOCATED;
- table_desc->length = sizeof (fadt_descriptor_rev2);
-
+ table_desc->pointer = (struct acpi_table_header *) acpi_gbl_FADT;
+ table_desc->allocation = ACPI_MEM_ALLOCATED;
+ table_desc->length = sizeof (struct fadt_descriptor_rev2);
/* Dump the entire FADT */
ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
"Hex dump of common internal FADT, size %d (%X)\n",
acpi_gbl_FADT->header.length, acpi_gbl_FADT->header.length));
- DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->header.length);
-
+ ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->header.length);
return_ACPI_STATUS (AE_OK);
}
@@ -487,82 +486,57 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_tb_convert_table_facs
+ * FUNCTION: acpi_tb_convert_table_facs
*
- * PARAMETERS:
+ * PARAMETERS: table_info - Info for currently installad FACS
*
- * RETURN:
+ * RETURN: Status
*
- * DESCRIPTION:
+ * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal
+ * table format.
*
******************************************************************************/
acpi_status
acpi_tb_build_common_facs (
- acpi_table_desc *table_info)
+ struct acpi_table_desc *table_info)
{
- acpi_common_facs *common_facs;
-
-#ifdef _IA64
- facs_descriptor_rev071 *FACS71;
-#else
- facs_descriptor_rev1 *FACS1;
-#endif
-
- facs_descriptor_rev2 *FACS2;
-
- FUNCTION_TRACE ("Tb_build_common_facs");
+ ACPI_FUNCTION_TRACE ("tb_build_common_facs");
- /* Allocate a common FACS */
+ /* Absolute minimum length is 24, but the ACPI spec says 64 */
- common_facs = ACPI_MEM_CALLOCATE (sizeof (acpi_common_facs));
- if (!common_facs) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ if (acpi_gbl_FACS->length < 24) {
+ ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n", acpi_gbl_FACS->length));
+ return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
}
+ if (acpi_gbl_FACS->length < 64) {
+ ACPI_REPORT_WARNING (("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n",
+ acpi_gbl_FACS->length));
+ }
/* Copy fields to the new FACS */
- if (acpi_gbl_RSDP->revision < 2) {
-#ifdef _IA64
- /* 0.71 FACS */
-
- FACS71 = (facs_descriptor_rev071 *) acpi_gbl_FACS;
-
- common_facs->global_lock = (u32 *) &(FACS71->global_lock);
- common_facs->firmware_waking_vector = &FACS71->firmware_waking_vector;
- common_facs->vector_width = 64;
-#else
- /* ACPI 1.0 FACS */
+ acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock);
- FACS1 = (facs_descriptor_rev1 *) acpi_gbl_FACS;
+ if ((acpi_gbl_RSDP->revision < 2) ||
+ (acpi_gbl_FACS->length < 32) ||
+ (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
+ /* ACPI 1.0 FACS or short table or optional X_ field is zero */
- common_facs->global_lock = &(FACS1->global_lock);
- common_facs->firmware_waking_vector = (u64 *) &FACS1->firmware_waking_vector;
- common_facs->vector_width = 32;
-
-#endif
+ acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR (u64, &(acpi_gbl_FACS->firmware_waking_vector));
+ acpi_gbl_common_fACS.vector_width = 32;
}
-
else {
- /* ACPI 2.0 FACS */
+ /* ACPI 2.0 FACS with valid X_ field */
- FACS2 = (facs_descriptor_rev2 *) acpi_gbl_FACS;
-
- common_facs->global_lock = &(FACS2->global_lock);
- common_facs->firmware_waking_vector = &FACS2->Xfirmware_waking_vector;
- common_facs->vector_width = 64;
+ acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->xfirmware_waking_vector;
+ acpi_gbl_common_fACS.vector_width = 64;
}
-
- /* Set the global FACS pointer to point to the common FACS */
-
-
- acpi_gbl_FACS = common_facs;
-
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS (AE_OK);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)