patch-2.4.0-test3 linux/drivers/acpi/tables/tbtable.c
Next file: linux/drivers/acpi/tables/tbutils.c
Previous file: linux/drivers/acpi/tables/tbinstal.c
Back to the patch index
Back to the overall index
- Lines: 389
- Date:
Wed Jul 5 11:23:13 2000
- Orig file:
v2.4.0-test2/linux/drivers/acpi/tables/tbtable.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/tables/tbtable.c linux/drivers/acpi/tables/tbtable.c
@@ -0,0 +1,388 @@
+
+/******************************************************************************
+ *
+ * Module Name: tbtable - ACPI tables: FACP, FACS, and RSDP utilities
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 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 "hardware.h"
+#include "tables.h"
+
+
+#define _COMPONENT TABLE_MANAGER
+ MODULE_NAME ("tbtable");
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_get_table_rsdt
+ *
+ * PARAMETERS: Number_of_tables - Where the table count is placed
+ * Table_ptr - Input buffer pointer, optional
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_tb_get_table_rsdt (
+ u32 *number_of_tables)
+{
+ ACPI_STATUS status = AE_OK;
+ ACPI_TABLE_DESC table_info;
+
+
+ /* Get the RSDP */
+
+ status = acpi_tb_find_rsdp (&table_info);
+ if (ACPI_FAILURE (status)) {
+ REPORT_WARNING ("RSDP structure not found");
+ return (AE_NO_ACPI_TABLES);
+ }
+
+ /* Save the table pointers and allocation info */
+
+ status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ acpi_gbl_RSDP = (ROOT_SYSTEM_DESCRIPTOR_POINTER *) table_info.pointer;
+
+
+ /*
+ * RSDP structure was found; Now get the RSDT
+ */
+
+ status = acpi_tb_get_table ((void *) acpi_gbl_RSDP->rsdt_physical_address, NULL,
+ &table_info);
+ if (ACPI_FAILURE (status)) {
+ if (status == AE_BAD_SIGNATURE) {
+ /* Invalid RSDT signature */
+
+ REPORT_ERROR ("Invalid signature where RSDP indicates RSDT should be located");
+
+ }
+ }
+
+
+ /* Always delete the RSDP mapping */
+
+ acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Save the table pointers and allocation info */
+
+ status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDT, &table_info);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ acpi_gbl_RSDT = (ROOT_SYSTEM_DESCRIPTION_TABLE *) table_info.pointer;
+
+
+ /* Valid RSDT signature, verify the checksum */
+
+ status = acpi_tb_verify_table_checksum ((ACPI_TABLE_HEADER *) acpi_gbl_RSDT);
+
+ /* Determine the number of tables pointed to by the RSDT */
+
+ *number_of_tables = (s32) DIV_4 (acpi_gbl_RSDT->header.length -
+ sizeof (ACPI_TABLE_HEADER));
+
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_scan_memory_for_rsdp
+ *
+ * PARAMETERS: Start_address - Starting pointer for search
+ * Length - Maximum length to search
+ *
+ * RETURN: Pointer to the RSDP if found, otherwise NULL.
+ *
+ * DESCRIPTION: Search a block of memory for the RSDP signature
+ *
+ ******************************************************************************/
+
+char *
+acpi_tb_scan_memory_for_rsdp (
+ char *start_address,
+ u32 length)
+{
+ u32 offset;
+ char *mem_rover;
+
+
+ /* Search from given start addr for the requested length */
+
+ for (offset = 0, mem_rover = start_address;
+ offset < length;
+ offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP)
+ {
+
+ /* The signature and checksum must both be correct */
+
+ if (STRNCMP (mem_rover, RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
+ acpi_tb_checksum (mem_rover,
+ sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER)) == 0)
+ {
+ /* If so, we have found the RSDP */
+
+ return mem_rover;
+ }
+ }
+
+ /* Searched entire block, no RSDP was found */
+
+ return NULL;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_find_rsdp
+ *
+ * PARAMETERS: *Buffer_ptr - If == NULL, read data from buffer
+ * rather than searching memory
+ * *Table_info - Where the table info is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
+ * pointer structure. If it is found, set *RSDP to point to it.
+ *
+ * NOTE: The RSDP must be either in the first 1_k of the Extended
+ * BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
+ * 5.2.2; assertion #421).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_tb_find_rsdp (
+ ACPI_TABLE_DESC *table_info)
+{
+ char *table_ptr;
+ char *mem_rover;
+ ACPI_STATUS status = AE_OK;
+
+ if (acpi_gbl_acpi_init_data.RSDP_physical_address) {
+ /*
+ * RSDP address was supplied as part of the initialization data
+ */
+
+ status = acpi_os_map_memory(acpi_gbl_acpi_init_data.RSDP_physical_address,
+ sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER),
+ (void **)&table_ptr);
+
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ if (!table_ptr) {
+ return (AE_NO_MEMORY);
+ }
+
+ /*
+ * The signature and checksum must both be correct
+ */
+
+ if (STRNCMP (table_ptr, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
+ /* Nope, BAD Signature */
+
+ return (AE_BAD_SIGNATURE);
+ }
+
+ /* The signature and checksum must both be correct */
+
+ if (acpi_tb_checksum (table_ptr,
+ sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER)) != 0)
+ {
+ /* Nope, BAD Checksum */
+
+ return (AE_BAD_CHECKSUM);
+ }
+
+ /* RSDP supplied is OK */
+ /* If so, we have found the RSDP */
+
+ table_info->pointer = (ACPI_TABLE_HEADER *) table_ptr;
+ table_info->length = sizeof (ROOT_SYSTEM_DESCRIPTOR_POINTER);
+ table_info->allocation = ACPI_MEM_MAPPED;
+ table_info->base_pointer = table_ptr;
+
+ return (AE_OK);
+ }
+
+ /*
+ * Search memory for RSDP. First map low physical memory.
+ */
+
+ status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE,
+ (void **)&table_ptr);
+
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /*
+ * 1) Search EBDA (low memory) paragraphs
+ */
+
+ if (NULL != (mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr,
+ LO_RSDP_WINDOW_SIZE)))
+ {
+ /* Found it, return pointer and don't delete the mapping */
+
+ table_info->pointer = (ACPI_TABLE_HEADER *) mem_rover;
+ table_info->length = LO_RSDP_WINDOW_SIZE;
+ table_info->allocation = ACPI_MEM_MAPPED;
+ table_info->base_pointer = table_ptr;
+
+ return (AE_OK);
+ }
+
+ /* This mapping is no longer needed */
+
+ acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE);
+
+
+ /*
+ * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+ */
+
+ status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE,
+ (void **)&table_ptr);
+
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ if (NULL != (mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr,
+ HI_RSDP_WINDOW_SIZE)))
+ {
+ /* Found it, return pointer and don't delete the mapping */
+
+ table_info->pointer = (ACPI_TABLE_HEADER *) mem_rover;
+ table_info->length = HI_RSDP_WINDOW_SIZE;
+ table_info->allocation = ACPI_MEM_MAPPED;
+ table_info->base_pointer = table_ptr;
+
+ return (AE_OK);
+ }
+
+ /* This mapping is no longer needed */
+
+ acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE);
+
+
+ /* RSDP signature was not found */
+
+ return (AE_NOT_FOUND);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_get_table_facs
+ *
+ * PARAMETERS: *Buffer_ptr - If == NULL, read data from buffer
+ * rather than searching memory
+ * *Table_info - Where the table info is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Returns a pointer to the FACS as defined in FACP. This
+ * function assumes the global variable FACP has been
+ * correctly initialized. The value of FACP->Firmware_ctrl
+ * into a far pointer which is returned.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_tb_get_table_facs (
+ char *buffer_ptr,
+ ACPI_TABLE_DESC *table_info)
+{
+ void *table_ptr = NULL;
+ u32 size;
+ u8 allocation;
+ ACPI_STATUS status = AE_OK;
+
+
+ /* Must have a valid FACP pointer */
+
+ if (!acpi_gbl_FACP) {
+ return (AE_NO_ACPI_TABLES);
+ }
+
+ size = sizeof (FIRMWARE_ACPI_CONTROL_STRUCTURE);
+ if (buffer_ptr) {
+ /*
+ * Getting table from a file -- allocate a buffer and
+ * read the table.
+ */
+ table_ptr = acpi_cm_allocate (size);
+ if(!table_ptr) {
+ return (AE_NO_MEMORY);
+ }
+
+ MEMCPY (table_ptr, buffer_ptr, size);
+
+ /* Save allocation type */
+
+ allocation = ACPI_MEM_ALLOCATED;
+ }
+
+ else {
+ /* Just map the physical memory to our address space */
+
+ status = acpi_tb_map_acpi_table ((void *) acpi_gbl_FACP->firmware_ctrl,
+ &size, &table_ptr);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Save allocation type */
+
+ allocation = ACPI_MEM_MAPPED;
+ }
+
+
+ /* Return values */
+
+ table_info->pointer = table_ptr;
+ table_info->length = size;
+ table_info->allocation = allocation;
+ table_info->base_pointer = table_ptr;
+
+ return (status);
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)