diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/resources | |
download | linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.bz2 |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/acpi/resources')
-rw-r--r-- | drivers/acpi/resources/Makefile | 10 | ||||
-rw-r--r-- | drivers/acpi/resources/rsaddr.c | 1225 | ||||
-rw-r--r-- | drivers/acpi/resources/rscalc.c | 841 | ||||
-rw-r--r-- | drivers/acpi/resources/rscreate.c | 428 | ||||
-rw-r--r-- | drivers/acpi/resources/rsdump.c | 1150 | ||||
-rw-r--r-- | drivers/acpi/resources/rsio.c | 545 | ||||
-rw-r--r-- | drivers/acpi/resources/rsirq.c | 592 | ||||
-rw-r--r-- | drivers/acpi/resources/rslist.c | 518 | ||||
-rw-r--r-- | drivers/acpi/resources/rsmemory.c | 566 | ||||
-rw-r--r-- | drivers/acpi/resources/rsmisc.c | 597 | ||||
-rw-r--r-- | drivers/acpi/resources/rsutils.c | 356 | ||||
-rw-r--r-- | drivers/acpi/resources/rsxface.c | 437 |
12 files changed, 7265 insertions, 0 deletions
diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile new file mode 100644 index 000000000000..2130b74170c3 --- /dev/null +++ b/drivers/acpi/resources/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for all Linux ACPI interpreter subdirectories +# + +obj-y := rsaddr.o rscreate.o rsio.o rslist.o rsmisc.o rsxface.o \ + rscalc.o rsirq.o rsmemory.o rsutils.o + +obj-$(ACPI_FUTURE_USAGE) += rsdump.o + +EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c new file mode 100644 index 000000000000..4788c079735d --- /dev/null +++ b/drivers/acpi/resources/rsaddr.c @@ -0,0 +1,1225 @@ +/******************************************************************************* + * + * Module Name: rsaddr - Address resource descriptors (16/32/64) + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsaddr") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_address16_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_address16_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u8 *temp_ptr; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16); + u32 index; + u16 temp16; + u8 temp8; + + + ACPI_FUNCTION_TRACE ("rs_address16_resource"); + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + /* Validate minimum descriptor length */ + + if (temp16 < 13) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + *bytes_consumed = temp16 + 3; + output_struct->id = ACPI_RSTYPE_ADDRESS16; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 and 0xC0-0xFF are valid */ + + if ((temp8 > 2) && (temp8 < 0xC0)) { + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + + output_struct->data.address16.resource_type = temp8; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* Producer / Consumer */ + + output_struct->data.address16.producer_consumer = temp8 & 0x01; + + /* Decode */ + + output_struct->data.address16.decode = (temp8 >> 1) & 0x01; + + /* Min Address Fixed */ + + output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01; + + /* Max Address Fixed */ + + output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (ACPI_MEMORY_RANGE == output_struct->data.address16.resource_type) { + output_struct->data.address16.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + output_struct->data.address16.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x03); + } + else { + if (ACPI_IO_RANGE == output_struct->data.address16.resource_type) { + output_struct->data.address16.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + output_struct->data.address16.attribute.io.translation_attribute = + (u16) ((temp8 >> 4) & 0x03); + } + else { + /* BUS_NUMBER_RANGE == Address16.Data->resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-7) + */ + buffer += 1; + ACPI_MOVE_16_TO_32 (&output_struct->data.address16.granularity, buffer); + + /* + * Get min_address_range (Bytes 8-9) + */ + buffer += 2; + ACPI_MOVE_16_TO_32 (&output_struct->data.address16.min_address_range, buffer); + + /* + * Get max_address_range (Bytes 10-11) + */ + buffer += 2; + ACPI_MOVE_16_TO_32 (&output_struct->data.address16.max_address_range, buffer); + + /* + * Get address_translation_offset (Bytes 12-13) + */ + buffer += 2; + ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_translation_offset, buffer); + + /* + * Get address_length (Bytes 14-15) + */ + buffer += 2; + ACPI_MOVE_16_TO_32 (&output_struct->data.address16.address_length, buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 2; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. + */ + if (*bytes_consumed > (16 + 1)) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address16.resource_source.index = (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* Point the String pointer to the end of this structure */ + + output_struct->data.address16.resource_source.string_ptr = + (char *)((u8 * )output_struct + struct_size); + + temp_ptr = (u8 *) output_struct->data.address16.resource_source.string_ptr; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + + output_struct->data.address16.resource_source.string_length = index + 1; + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); + } + else { + output_struct->data.address16.resource_source.index = 0x00; + output_struct->data.address16.resource_source.string_length = 0; + output_struct->data.address16.resource_source.string_ptr = NULL; + } + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_address16_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_address16_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 *length_field; + u8 temp8; + char *temp_pointer = NULL; + acpi_size actual_bytes; + + + ACPI_FUNCTION_TRACE ("rs_address16_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x88; + buffer += 1; + + /* + * Save a pointer to the Length field - to be filled in later + */ + length_field = buffer; + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, bus_number) + */ + temp8 = (u8) (linked_list->data.address16.resource_type & 0x03); + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01); + + temp8 |= (linked_list->data.address16.decode & 0x01) << 1; + temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if (ACPI_MEMORY_RANGE == linked_list->data.address16.resource_type) { + temp8 = (u8) + (linked_list->data.address16.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address16.attribute.memory.cache_attribute & + 0x03) << 1; + } + else if (ACPI_IO_RANGE == linked_list->data.address16.resource_type) { + temp8 = (u8) + (linked_list->data.address16.attribute.io.range_attribute & + 0x03); + temp8 |= + (linked_list->data.address16.attribute.io.translation_attribute & + 0x03) << 4; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.granularity); + buffer += 2; + + /* + * Set the address range minimum + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.min_address_range); + buffer += 2; + + /* + * Set the address range maximum + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.max_address_range); + buffer += 2; + + /* + * Set the address translation offset + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_translation_offset); + buffer += 2; + + /* + * Set the address length + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.address16.address_length); + buffer += 2; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address16.resource_source.string_length) { + temp8 = (u8) linked_list->data.address16.resource_source.index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = (char *) buffer; + + /* + * Copy the string + */ + ACPI_STRCPY (temp_pointer, + linked_list->data.address16.resource_source.string_ptr); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address16.resource_source.string_ptr) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + actual_bytes = ACPI_PTR_DIFF (buffer, *output_buffer); + *bytes_consumed = actual_bytes; + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + actual_bytes -= 3; + ACPI_MOVE_SIZE_TO_16 (length_field, &actual_bytes); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_address32_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_address32_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer; + struct acpi_resource *output_struct= (void *) *output_buffer; + u16 temp16; + u8 temp8; + u8 *temp_ptr; + acpi_size struct_size; + u32 index; + + + ACPI_FUNCTION_TRACE ("rs_address32_resource"); + + + buffer = byte_stream_buffer; + struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32); + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + /* Validate minimum descriptor length */ + + if (temp16 < 23) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + *bytes_consumed = temp16 + 3; + output_struct->id = ACPI_RSTYPE_ADDRESS32; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 and 0xC0-0xFF are valid */ + + if ((temp8 > 2) && (temp8 < 0xC0)) { + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + + output_struct->data.address32.resource_type = temp8; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address32.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address32.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (ACPI_MEMORY_RANGE == output_struct->data.address32.resource_type) { + output_struct->data.address32.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + + output_struct->data.address32.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x03); + } + else { + if (ACPI_IO_RANGE == output_struct->data.address32.resource_type) { + output_struct->data.address32.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + output_struct->data.address32.attribute.io.translation_attribute = + (u16) ((temp8 >> 4) & 0x03); + } + else { + /* BUS_NUMBER_RANGE == output_struct->Data.Address32.resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-9) + */ + buffer += 1; + ACPI_MOVE_32_TO_32 (&output_struct->data.address32.granularity, buffer); + + /* + * Get min_address_range (Bytes 10-13) + */ + buffer += 4; + ACPI_MOVE_32_TO_32 (&output_struct->data.address32.min_address_range, buffer); + + /* + * Get max_address_range (Bytes 14-17) + */ + buffer += 4; + ACPI_MOVE_32_TO_32 (&output_struct->data.address32.max_address_range, buffer); + + /* + * Get address_translation_offset (Bytes 18-21) + */ + buffer += 4; + ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_translation_offset, buffer); + + /* + * Get address_length (Bytes 22-25) + */ + buffer += 4; + ACPI_MOVE_32_TO_32 (&output_struct->data.address32.address_length, buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 4; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. + */ + if (*bytes_consumed > (26 + 1)) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address32.resource_source.index = + (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* Point the String pointer to the end of this structure */ + + output_struct->data.address32.resource_source.string_ptr = + (char *)((u8 *)output_struct + struct_size); + + temp_ptr = (u8 *) output_struct->data.address32.resource_source.string_ptr; + + /* Copy the string into the buffer */ + + index = 0; + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + output_struct->data.address32.resource_source.string_length = index + 1; + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); + } + else { + output_struct->data.address32.resource_source.index = 0x00; + output_struct->data.address32.resource_source.string_length = 0; + output_struct->data.address32.resource_source.string_ptr = NULL; + } + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_address32_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_address32_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer; + u16 *length_field; + u8 temp8; + char *temp_pointer; + + + ACPI_FUNCTION_TRACE ("rs_address32_stream"); + + + buffer = *output_buffer; + + /* + * The descriptor field is static + */ + *buffer = 0x87; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + length_field = ACPI_CAST_PTR (u16, buffer); + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, bus_number) + */ + temp8 = (u8) (linked_list->data.address32.resource_type & 0x03); + + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01); + temp8 |= (linked_list->data.address32.decode & 0x01) << 1; + temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if (ACPI_MEMORY_RANGE == linked_list->data.address32.resource_type) { + temp8 = (u8) + (linked_list->data.address32.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address32.attribute.memory.cache_attribute & + 0x03) << 1; + } + else if (ACPI_IO_RANGE == linked_list->data.address32.resource_type) { + temp8 = (u8) + (linked_list->data.address32.attribute.io.range_attribute & + 0x03); + temp8 |= + (linked_list->data.address32.attribute.io.translation_attribute & + 0x03) << 4; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.granularity); + buffer += 4; + + /* + * Set the address range minimum + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.min_address_range); + buffer += 4; + + /* + * Set the address range maximum + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.max_address_range); + buffer += 4; + + /* + * Set the address translation offset + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_translation_offset); + buffer += 4; + + /* + * Set the address length + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.address32.address_length); + buffer += 4; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address32.resource_source.string_length) { + temp8 = (u8) linked_list->data.address32.resource_source.index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = (char *) buffer; + + /* + * Copy the string + */ + ACPI_STRCPY (temp_pointer, + linked_list->data.address32.resource_source.string_ptr); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address32.resource_source.string_ptr) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_address64_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_address64_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16; + u8 temp8; + u8 resource_type; + u8 *temp_ptr; + acpi_size struct_size; + u32 index; + + + ACPI_FUNCTION_TRACE ("rs_address64_resource"); + + + buffer = byte_stream_buffer; + struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); + resource_type = *buffer; + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + /* Validate minimum descriptor length */ + + if (temp16 < 43) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + *bytes_consumed = temp16 + 3; + output_struct->id = ACPI_RSTYPE_ADDRESS64; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 and 0xC0-0xFF are valid */ + + if ((temp8 > 2) && (temp8 < 0xC0)) { + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + + output_struct->data.address64.resource_type = temp8; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address64.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address64.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address64.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address64.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (ACPI_MEMORY_RANGE == output_struct->data.address64.resource_type) { + output_struct->data.address64.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + + output_struct->data.address64.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x03); + } + else { + if (ACPI_IO_RANGE == output_struct->data.address64.resource_type) { + output_struct->data.address64.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + output_struct->data.address64.attribute.io.translation_attribute = + (u16) ((temp8 >> 4) & 0x03); + } + else { + /* BUS_NUMBER_RANGE == output_struct->Data.Address64.resource_type */ + /* Nothing needs to be filled in */ + } + } + + if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { + /* Move past revision_id and Reserved byte */ + + buffer += 2; + } + + /* + * Get Granularity (Bytes 6-13) or (Bytes 8-15) + */ + buffer += 1; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer); + + /* + * Get min_address_range (Bytes 14-21) or (Bytes 16-23) + */ + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer); + + /* + * Get max_address_range (Bytes 22-29) or (Bytes 24-31) + */ + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer); + + /* + * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39) + */ + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer); + + /* + * Get address_length (Bytes 38-45) or (Bytes 40-47) + */ + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer); + + output_struct->data.address64.resource_source.index = 0x00; + output_struct->data.address64.resource_source.string_length = 0; + output_struct->data.address64.resource_source.string_ptr = NULL; + + if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) { + /* Get type_specific_attribute (Bytes 48-55) */ + + buffer += 8; + ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer); + } + else { + output_struct->data.address64.type_specific_attributes = 0; + + /* + * Resource Source Index (if present) + */ + buffer += 8; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. + */ + if (*bytes_consumed > (46 + 1)) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address64.resource_source.index = + (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* Point the String pointer to the end of this structure */ + + output_struct->data.address64.resource_source.string_ptr = + (char *)((u8 *)output_struct + struct_size); + + temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr; + + /* Copy the string into the buffer */ + + index = 0; + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + output_struct->data.address64.resource_source.string_length = index + 1; + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); + } + } + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_address64_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_address64_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer; + u16 *length_field; + u8 temp8; + char *temp_pointer; + + + ACPI_FUNCTION_TRACE ("rs_address64_stream"); + + + buffer = *output_buffer; + + /* + * The descriptor field is static + */ + *buffer = 0x8A; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + length_field = ACPI_CAST_PTR (u16, buffer); + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, bus_number) + */ + temp8 = (u8) (linked_list->data.address64.resource_type & 0x03); + + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address64.producer_consumer & 0x01); + temp8 |= (linked_list->data.address64.decode & 0x01) << 1; + temp8 |= (linked_list->data.address64.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address64.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if (ACPI_MEMORY_RANGE == linked_list->data.address64.resource_type) { + temp8 = (u8) + (linked_list->data.address64.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address64.attribute.memory.cache_attribute & + 0x03) << 1; + } + else if (ACPI_IO_RANGE == linked_list->data.address64.resource_type) { + temp8 = (u8) + (linked_list->data.address64.attribute.io.range_attribute & + 0x03); + temp8 |= + (linked_list->data.address64.attribute.io.range_attribute & + 0x03) << 4; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.granularity); + buffer += 8; + + /* + * Set the address range minimum + */ + ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.min_address_range); + buffer += 8; + + /* + * Set the address range maximum + */ + ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.max_address_range); + buffer += 8; + + /* + * Set the address translation offset + */ + ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_translation_offset); + buffer += 8; + + /* + * Set the address length + */ + ACPI_MOVE_64_TO_64 (buffer, &linked_list->data.address64.address_length); + buffer += 8; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address64.resource_source.string_length) { + temp8 = (u8) linked_list->data.address64.resource_source.index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = (char *) buffer; + + /* + * Copy the string + */ + ACPI_STRCPY (temp_pointer, linked_list->data.address64.resource_source.string_ptr); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.address64.resource_source.string_ptr) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c new file mode 100644 index 000000000000..8a5f0a52371d --- /dev/null +++ b/drivers/acpi/resources/rscalc.c @@ -0,0 +1,841 @@ +/******************************************************************************* + * + * Module Name: rscalc - Calculate stream and list lengths + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> +#include <acpi/amlcode.h> +#include <acpi/acnamesp.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rscalc") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_byte_stream_length + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * size_needed - u32 pointer of the size buffer needed + * to properly return the parsed data + * + * RETURN: Status + * + * DESCRIPTION: Takes the resource byte stream and parses it once, calculating + * the size buffer needed to hold the linked list that conveys + * the resource data. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_byte_stream_length ( + struct acpi_resource *linked_list, + acpi_size *size_needed) +{ + acpi_size byte_stream_size_needed = 0; + acpi_size segment_size; + u8 done = FALSE; + + + ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length"); + + + while (!done) { + /* + * Init the variable that will hold the size to add to the total. + */ + segment_size = 0; + + switch (linked_list->id) { + case ACPI_RSTYPE_IRQ: + /* + * IRQ Resource + * For an IRQ Resource, Byte 3, although optional, will always be + * created - it holds IRQ information. + */ + segment_size = 4; + break; + + case ACPI_RSTYPE_DMA: + /* + * DMA Resource + * For this resource the size is static + */ + segment_size = 3; + break; + + case ACPI_RSTYPE_START_DPF: + /* + * Start Dependent Functions Resource + * For a start_dependent_functions Resource, Byte 1, although + * optional, will always be created. + */ + segment_size = 2; + break; + + case ACPI_RSTYPE_END_DPF: + /* + * End Dependent Functions Resource + * For this resource the size is static + */ + segment_size = 1; + break; + + case ACPI_RSTYPE_IO: + /* + * IO Port Resource + * For this resource the size is static + */ + segment_size = 8; + break; + + case ACPI_RSTYPE_FIXED_IO: + /* + * Fixed IO Port Resource + * For this resource the size is static + */ + segment_size = 4; + break; + + case ACPI_RSTYPE_VENDOR: + /* + * Vendor Defined Resource + * For a Vendor Specific resource, if the Length is between 1 and 7 + * it will be created as a Small Resource data type, otherwise it + * is a Large Resource data type. + */ + if (linked_list->data.vendor_specific.length > 7) { + segment_size = 3; + } + else { + segment_size = 1; + } + segment_size += linked_list->data.vendor_specific.length; + break; + + case ACPI_RSTYPE_END_TAG: + /* + * End Tag + * For this resource the size is static + */ + segment_size = 2; + done = TRUE; + break; + + case ACPI_RSTYPE_MEM24: + /* + * 24-Bit Memory Resource + * For this resource the size is static + */ + segment_size = 12; + break; + + case ACPI_RSTYPE_MEM32: + /* + * 32-Bit Memory Range Resource + * For this resource the size is static + */ + segment_size = 20; + break; + + case ACPI_RSTYPE_FIXED_MEM32: + /* + * 32-Bit Fixed Memory Resource + * For this resource the size is static + */ + segment_size = 12; + break; + + case ACPI_RSTYPE_ADDRESS16: + /* + * 16-Bit Address Resource + * The base size of this byte stream is 16. If a Resource Source + * string is not NULL, add 1 for the Index + the length of the null + * terminated string Resource Source + 1 for the null. + */ + segment_size = 16; + + if (linked_list->data.address16.resource_source.string_ptr) { + segment_size += linked_list->data.address16.resource_source.string_length; + segment_size++; + } + break; + + case ACPI_RSTYPE_ADDRESS32: + /* + * 32-Bit Address Resource + * The base size of this byte stream is 26. If a Resource + * Source string is not NULL, add 1 for the Index + the + * length of the null terminated string Resource Source + + * 1 for the null. + */ + segment_size = 26; + + if (linked_list->data.address32.resource_source.string_ptr) { + segment_size += linked_list->data.address32.resource_source.string_length; + segment_size++; + } + break; + + case ACPI_RSTYPE_ADDRESS64: + /* + * 64-Bit Address Resource + * The base size of this byte stream is 46. If a resource_source + * string is not NULL, add 1 for the Index + the length of the null + * terminated string Resource Source + 1 for the null. + */ + segment_size = 46; + + if (linked_list->data.address64.resource_source.string_ptr) { + segment_size += linked_list->data.address64.resource_source.string_length; + segment_size++; + } + break; + + case ACPI_RSTYPE_EXT_IRQ: + /* + * Extended IRQ Resource + * The base size of this byte stream is 9. This is for an Interrupt + * table length of 1. For each additional interrupt, add 4. + * If a Resource Source string is not NULL, add 1 for the + * Index + the length of the null terminated string + * Resource Source + 1 for the null. + */ + segment_size = 9 + + (((acpi_size) linked_list->data.extended_irq.number_of_interrupts - 1) * 4); + + if (linked_list->data.extended_irq.resource_source.string_ptr) { + segment_size += linked_list->data.extended_irq.resource_source.string_length; + segment_size++; + } + break; + + default: + /* + * If we get here, everything is out of sync, exit with error + */ + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + + } /* switch (linked_list->Id) */ + + /* + * Update the total + */ + byte_stream_size_needed += segment_size; + + /* + * Point to the next object + */ + linked_list = ACPI_PTR_ADD (struct acpi_resource, + linked_list, linked_list->length); + } + + /* + * This is the data the caller needs + */ + *size_needed = byte_stream_size_needed; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_list_length + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream + * byte_stream_buffer_length - Size of byte_stream_buffer + * size_needed - u32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status + * + * DESCRIPTION: Takes the resource byte stream and parses it once, calculating + * the size buffer needed to hold the linked list that conveys + * the resource data. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_list_length ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + acpi_size *size_needed) +{ + u32 buffer_size = 0; + u32 bytes_parsed = 0; + u8 number_of_interrupts = 0; + u8 number_of_channels = 0; + u8 resource_type; + u32 structure_size; + u32 bytes_consumed; + u8 *buffer; + u8 temp8; + u16 temp16; + u8 index; + u8 additional_bytes; + + + ACPI_FUNCTION_TRACE ("rs_get_list_length"); + + + while (bytes_parsed < byte_stream_buffer_length) { + /* + * The next byte in the stream is the resource type + */ + resource_type = acpi_rs_get_resource_type (*byte_stream_buffer); + + switch (resource_type) { + case ACPI_RDESC_TYPE_MEMORY_24: + /* + * 24-Bit Memory Resource + */ + bytes_consumed = 12; + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24); + break; + + + case ACPI_RDESC_TYPE_LARGE_VENDOR: + /* + * Vendor Defined Resource + */ + buffer = byte_stream_buffer; + ++buffer; + + ACPI_MOVE_16_TO_16 (&temp16, buffer); + bytes_consumed = temp16 + 3; + + /* + * Ensure a 32-bit boundary for the structure + */ + temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16); + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) + + (temp16 * sizeof (u8)); + break; + + + case ACPI_RDESC_TYPE_MEMORY_32: + /* + * 32-Bit Memory Range Resource + */ + bytes_consumed = 20; + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32); + break; + + + case ACPI_RDESC_TYPE_FIXED_MEMORY_32: + /* + * 32-Bit Fixed Memory Resource + */ + bytes_consumed = 12; + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32); + break; + + + case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64); + break; + + + case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 43, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. + */ + if (43 < temp16) { + temp8 = (u8) (temp16 - 44); + } + else { + temp8 = 0; + } + + /* + * Ensure a 64-bit boundary for the structure + */ + temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8); + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) + + (temp8 * sizeof (u8)); + break; + + + case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 23, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. + */ + if (23 < temp16) { + temp8 = (u8) (temp16 - 24); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) + + (temp8 * sizeof (u8)); + break; + + + case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 13, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. + */ + if (13 < temp16) { + temp8 = (u8) (temp16 - 14); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) + + (temp8 * sizeof (u8)); + break; + + + case ACPI_RDESC_TYPE_EXTENDED_XRUPT: + /* + * Extended IRQ + */ + buffer = byte_stream_buffer; + + ++buffer; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Point past the length field and the Interrupt vector flags to + * save off the Interrupt table length to the Temp8 variable. + */ + buffer += 3; + temp8 = *buffer; + + /* + * To compensate for multiple interrupt numbers, add 4 bytes for + * each additional interrupts greater than 1 + */ + additional_bytes = (u8) ((temp8 - 1) * 4); + + /* + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 9, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. + */ + if (9 + additional_bytes < temp16) { + temp8 = (u8) (temp16 - (9 + additional_bytes)); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) + + (additional_bytes * sizeof (u8)) + + (temp8 * sizeof (u8)); + break; + + + case ACPI_RDESC_TYPE_IRQ_FORMAT: + /* + * IRQ Resource. + * Determine if it there are two or three trailing bytes + */ + buffer = byte_stream_buffer; + temp8 = *buffer; + + if(temp8 & 0x01) { + bytes_consumed = 4; + } + else { + bytes_consumed = 3; + } + + /* Point past the descriptor */ + + ++buffer; + + /* + * Look at the number of bits set + */ + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + for (index = 0; index < 16; index++) { + if (temp16 & 0x1) { + ++number_of_interrupts; + } + + temp16 >>= 1; + } + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) + + (number_of_interrupts * sizeof (u32)); + break; + + + case ACPI_RDESC_TYPE_DMA_FORMAT: + /* + * DMA Resource + */ + buffer = byte_stream_buffer; + bytes_consumed = 3; + + /* Point past the descriptor */ + + ++buffer; + + /* + * Look at the number of bits set + */ + temp8 = *buffer; + + for(index = 0; index < 8; index++) { + if(temp8 & 0x1) { + ++number_of_channels; + } + + temp8 >>= 1; + } + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) + + (number_of_channels * sizeof (u32)); + break; + + + case ACPI_RDESC_TYPE_START_DEPENDENT: + /* + * Start Dependent Functions Resource + * Determine if it there are two or three trailing bytes + */ + buffer = byte_stream_buffer; + temp8 = *buffer; + + if(temp8 & 0x01) { + bytes_consumed = 2; + } + else { + bytes_consumed = 1; + } + + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf); + break; + + + case ACPI_RDESC_TYPE_END_DEPENDENT: + /* + * End Dependent Functions Resource + */ + bytes_consumed = 1; + structure_size = ACPI_RESOURCE_LENGTH; + break; + + + case ACPI_RDESC_TYPE_IO_PORT: + /* + * IO Port Resource + */ + bytes_consumed = 8; + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io); + break; + + + case ACPI_RDESC_TYPE_FIXED_IO_PORT: + /* + * Fixed IO Port Resource + */ + bytes_consumed = 4; + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io); + break; + + + case ACPI_RDESC_TYPE_SMALL_VENDOR: + /* + * Vendor Specific Resource + */ + buffer = byte_stream_buffer; + + temp8 = *buffer; + temp8 = (u8) (temp8 & 0x7); + bytes_consumed = temp8 + 1; + + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8); + structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) + + (temp8 * sizeof (u8)); + break; + + + case ACPI_RDESC_TYPE_END_TAG: + /* + * End Tag + */ + bytes_consumed = 2; + structure_size = ACPI_RESOURCE_LENGTH; + byte_stream_buffer_length = bytes_parsed; + break; + + + default: + /* + * If we get here, everything is out of sync, + * exit with an error + */ + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* + * Update the return value and counter + */ + buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size); + bytes_parsed += bytes_consumed; + + /* + * Set the byte stream to point to the next resource + */ + byte_stream_buffer += bytes_consumed; + } + + /* + * This is the data the caller needs + */ + *size_needed = buffer_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_pci_routing_table_length + * + * PARAMETERS: package_object - Pointer to the package object + * buffer_size_needed - u32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status + * + * DESCRIPTION: Given a package representing a PCI routing table, this + * calculates the size of the corresponding linked list of + * descriptions. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_pci_routing_table_length ( + union acpi_operand_object *package_object, + acpi_size *buffer_size_needed) +{ + u32 number_of_elements; + acpi_size temp_size_needed = 0; + union acpi_operand_object **top_object_list; + u32 index; + union acpi_operand_object *package_element; + union acpi_operand_object **sub_object_list; + u8 name_found; + u32 table_index; + + + ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length"); + + + number_of_elements = package_object->package.count; + + /* + * Calculate the size of the return buffer. + * The base size is the number of elements * the sizes of the + * structures. Additional space for the strings is added below. + * The minus one is to subtract the size of the u8 Source[1] + * member because it is added below. + * + * But each PRT_ENTRY structure has a pointer to a string and + * the size of that string must be found. + */ + top_object_list = package_object->package.elements; + + for (index = 0; index < number_of_elements; index++) { + /* + * Dereference the sub-package + */ + package_element = *top_object_list; + + /* + * The sub_object_list will now point to an array of the + * four IRQ elements: Address, Pin, Source and source_index + */ + sub_object_list = package_element->package.elements; + + /* + * Scan the irq_table_elements for the Source Name String + */ + name_found = FALSE; + + for (table_index = 0; table_index < 4 && !name_found; table_index++) { + if ((ACPI_TYPE_STRING == ACPI_GET_OBJECT_TYPE (*sub_object_list)) || + ((ACPI_TYPE_LOCAL_REFERENCE == ACPI_GET_OBJECT_TYPE (*sub_object_list)) && + ((*sub_object_list)->reference.opcode == AML_INT_NAMEPATH_OP))) { + name_found = TRUE; + } + else { + /* + * Look at the next element + */ + sub_object_list++; + } + } + + temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4); + + /* + * Was a String type found? + */ + if (name_found) { + if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) { + /* + * The length String.Length field does not include the + * terminating NULL, add 1 + */ + temp_size_needed += ((acpi_size) (*sub_object_list)->string.length + 1); + } + else { + temp_size_needed += acpi_ns_get_pathname_length ( + (*sub_object_list)->reference.node); + } + } + else { + /* + * If no name was found, then this is a NULL, which is + * translated as a u32 zero. + */ + temp_size_needed += sizeof (u32); + } + + /* Round up the size since each element must be aligned */ + + temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed); + + /* + * Point to the next union acpi_operand_object + */ + top_object_list++; + } + + /* + * Adding an extra element to the end of the list, essentially a NULL terminator + */ + *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table); + return_ACPI_STATUS (AE_OK); +} diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c new file mode 100644 index 000000000000..a3a0cbfda68d --- /dev/null +++ b/drivers/acpi/resources/rscreate.c @@ -0,0 +1,428 @@ +/******************************************************************************* + * + * Module Name: rscreate - Create resource lists/tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> +#include <acpi/amlcode.h> +#include <acpi/acnamesp.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rscreate") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_create_resource_list + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream + * output_buffer - Pointer to the user's buffer + * + * RETURN: Status - AE_OK if okay, else a valid acpi_status code + * If output_buffer is not large enough, output_buffer_length + * indicates how large output_buffer should be, else it + * indicates how may u8 elements of output_buffer are valid. + * + * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method + * execution and parses the stream to create a linked list + * of device resources. + * + ******************************************************************************/ + +acpi_status +acpi_rs_create_resource_list ( + union acpi_operand_object *byte_stream_buffer, + struct acpi_buffer *output_buffer) +{ + + acpi_status status; + u8 *byte_stream_start; + acpi_size list_size_needed = 0; + u32 byte_stream_buffer_length; + + + ACPI_FUNCTION_TRACE ("rs_create_resource_list"); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_buffer = %p\n", + byte_stream_buffer)); + + /* + * Params already validated, so we don't re-validate here + */ + byte_stream_buffer_length = byte_stream_buffer->buffer.length; + byte_stream_start = byte_stream_buffer->buffer.pointer; + + /* + * Pass the byte_stream_buffer into a module that can calculate + * the buffer size needed for the linked list + */ + status = acpi_rs_get_list_length (byte_stream_start, byte_stream_buffer_length, + &list_size_needed); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n", + status, (u32) list_size_needed)); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (output_buffer, list_size_needed); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Do the conversion */ + + status = acpi_rs_byte_stream_to_list (byte_stream_start, byte_stream_buffer_length, + output_buffer->pointer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n", + output_buffer->pointer, (u32) output_buffer->length)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_create_pci_routing_table + * + * PARAMETERS: package_object - Pointer to an union acpi_operand_object + * package + * output_buffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid acpi_status code. + * If the output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and output_buffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the union acpi_operand_object package and creates a + * linked list of PCI interrupt descriptions + * + * NOTE: It is the caller's responsibility to ensure that the start of the + * output buffer is aligned properly (if necessary). + * + ******************************************************************************/ + +acpi_status +acpi_rs_create_pci_routing_table ( + union acpi_operand_object *package_object, + struct acpi_buffer *output_buffer) +{ + u8 *buffer; + union acpi_operand_object **top_object_list; + union acpi_operand_object **sub_object_list; + union acpi_operand_object *obj_desc; + acpi_size buffer_size_needed = 0; + u32 number_of_elements; + u32 index; + struct acpi_pci_routing_table *user_prt; + struct acpi_namespace_node *node; + acpi_status status; + struct acpi_buffer path_buffer; + + + ACPI_FUNCTION_TRACE ("rs_create_pci_routing_table"); + + + /* Params already validated, so we don't re-validate here */ + + /* + * Get the required buffer length + */ + status = acpi_rs_get_pci_routing_table_length (package_object, + &buffer_size_needed); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "buffer_size_needed = %X\n", + (u32) buffer_size_needed)); + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (output_buffer, buffer_size_needed); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Loop through the ACPI_INTERNAL_OBJECTS - Each object + * should be a package that in turn contains an + * acpi_integer Address, a u8 Pin, a Name and a u8 source_index. + */ + top_object_list = package_object->package.elements; + number_of_elements = package_object->package.count; + buffer = output_buffer->pointer; + user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer); + + for (index = 0; index < number_of_elements; index++) { + /* + * Point user_prt past this current structure + * + * NOTE: On the first iteration, user_prt->Length will + * be zero because we cleared the return buffer earlier + */ + buffer += user_prt->length; + user_prt = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer); + + /* + * Fill in the Length field with the information we have at this point. + * The minus four is to subtract the size of the u8 Source[4] member + * because it is added below. + */ + user_prt->length = (sizeof (struct acpi_pci_routing_table) - 4); + + /* + * Each element of the top-level package must also be a package + */ + if (ACPI_GET_OBJECT_TYPE (*top_object_list) != ACPI_TYPE_PACKAGE) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X]) Need sub-package, found %s\n", + index, acpi_ut_get_object_type_name (*top_object_list))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Each sub-package must be of length 4 */ + + if ((*top_object_list)->package.count != 4) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X]) Need package of length 4, found length %d\n", + index, (*top_object_list)->package.count)); + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + + /* + * Dereference the sub-package. + * The sub_object_list will now point to an array of the four IRQ + * elements: [Address, Pin, Source, source_index] + */ + sub_object_list = (*top_object_list)->package.elements; + + /* + * 1) First subobject: Dereference the PRT.Address + */ + obj_desc = sub_object_list[0]; + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { + user_prt->address = obj_desc->integer.value; + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X].Address) Need Integer, found %s\n", + index, acpi_ut_get_object_type_name (obj_desc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* + * 2) Second subobject: Dereference the PRT.Pin + */ + obj_desc = sub_object_list[1]; + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { + user_prt->pin = (u32) obj_desc->integer.value; + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X].Pin) Need Integer, found %s\n", + index, acpi_ut_get_object_type_name (obj_desc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* + * 3) Third subobject: Dereference the PRT.source_name + */ + obj_desc = sub_object_list[2]; + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_LOCAL_REFERENCE: + + if (obj_desc->reference.opcode != AML_INT_NAMEPATH_OP) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X].Source) Need name, found reference op %X\n", + index, obj_desc->reference.opcode)); + return_ACPI_STATUS (AE_BAD_DATA); + } + + node = obj_desc->reference.node; + + /* Use *remaining* length of the buffer as max for pathname */ + + path_buffer.length = output_buffer->length - + (u32) ((u8 *) user_prt->source - + (u8 *) output_buffer->pointer); + path_buffer.pointer = user_prt->source; + + status = acpi_ns_handle_to_pathname ((acpi_handle) node, &path_buffer); + + user_prt->length += (u32) ACPI_STRLEN (user_prt->source) + 1; /* include null terminator */ + break; + + + case ACPI_TYPE_STRING: + + ACPI_STRCPY (user_prt->source, obj_desc->string.pointer); + + /* Add to the Length field the length of the string (add 1 for terminator) */ + + user_prt->length += obj_desc->string.length + 1; + break; + + + case ACPI_TYPE_INTEGER: + /* + * If this is a number, then the Source Name is NULL, since the + * entire buffer was zeroed out, we can leave this alone. + * + * Add to the Length field the length of the u32 NULL + */ + user_prt->length += sizeof (u32); + break; + + + default: + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X].Source) Need Ref/String/Integer, found %s\n", + index, acpi_ut_get_object_type_name (obj_desc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* Now align the current length */ + + user_prt->length = (u32) ACPI_ROUND_UP_to_64_bITS (user_prt->length); + + /* + * 4) Fourth subobject: Dereference the PRT.source_index + */ + obj_desc = sub_object_list[3]; + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { + user_prt->source_index = (u32) obj_desc->integer.value; + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "(PRT[%X].source_index) Need Integer, found %s\n", + index, acpi_ut_get_object_type_name (obj_desc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* Point to the next union acpi_operand_object in the top level package */ + + top_object_list++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n", + output_buffer->pointer, (u32) output_buffer->length)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_create_byte_stream + * + * PARAMETERS: linked_list_buffer - Pointer to the resource linked list + * output_buffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid acpi_status code. + * If the output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and output_buffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the linked list of device resources and + * creates a bytestream to be used as input for the + * _SRS control method. + * + ******************************************************************************/ + +acpi_status +acpi_rs_create_byte_stream ( + struct acpi_resource *linked_list_buffer, + struct acpi_buffer *output_buffer) +{ + acpi_status status; + acpi_size byte_stream_size_needed = 0; + + + ACPI_FUNCTION_TRACE ("rs_create_byte_stream"); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "linked_list_buffer = %p\n", + linked_list_buffer)); + + /* + * Params already validated, so we don't re-validate here + * + * Pass the linked_list_buffer into a module that calculates + * the buffer size needed for the byte stream. + */ + status = acpi_rs_get_byte_stream_length (linked_list_buffer, + &byte_stream_size_needed); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "byte_stream_size_needed=%X, %s\n", + (u32) byte_stream_size_needed, acpi_format_exception (status))); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (output_buffer, byte_stream_size_needed); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Do the conversion */ + + status = acpi_rs_list_to_byte_stream (linked_list_buffer, byte_stream_size_needed, + output_buffer->pointer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "output_buffer %p Length %X\n", + output_buffer->pointer, (u32) output_buffer->length)); + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c new file mode 100644 index 000000000000..eef1b1f2c685 --- /dev/null +++ b/drivers/acpi/resources/rsdump.c @@ -0,0 +1,1150 @@ +/******************************************************************************* + * + * Module Name: rsdump - Functions to display the resource structures. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsdump") + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_irq + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_irq ( + union acpi_resource_data *data) +{ + struct acpi_resource_irq *irq_data = (struct acpi_resource_irq *) data; + u8 index = 0; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("IRQ Resource\n"); + + acpi_os_printf (" %s Triggered\n", + ACPI_LEVEL_SENSITIVE == irq_data->edge_level ? "Level" : "Edge"); + + acpi_os_printf (" Active %s\n", + ACPI_ACTIVE_LOW == irq_data->active_high_low ? "Low" : "High"); + + acpi_os_printf (" %s\n", + ACPI_SHARED == irq_data->shared_exclusive ? "Shared" : "Exclusive"); + + acpi_os_printf (" %X Interrupts ( ", irq_data->number_of_interrupts); + + for (index = 0; index < irq_data->number_of_interrupts; index++) { + acpi_os_printf ("%X ", irq_data->interrupts[index]); + } + + acpi_os_printf (")\n"); + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_dma + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_dma ( + union acpi_resource_data *data) +{ + struct acpi_resource_dma *dma_data = (struct acpi_resource_dma *) data; + u8 index = 0; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("DMA Resource\n"); + + switch (dma_data->type) { + case ACPI_COMPATIBILITY: + acpi_os_printf (" Compatibility mode\n"); + break; + + case ACPI_TYPE_A: + acpi_os_printf (" Type A\n"); + break; + + case ACPI_TYPE_B: + acpi_os_printf (" Type B\n"); + break; + + case ACPI_TYPE_F: + acpi_os_printf (" Type F\n"); + break; + + default: + acpi_os_printf (" Invalid DMA type\n"); + break; + } + + acpi_os_printf (" %sBus Master\n", + ACPI_BUS_MASTER == dma_data->bus_master ? "" : "Not a "); + + + switch (dma_data->transfer) { + case ACPI_TRANSFER_8: + acpi_os_printf (" 8-bit only transfer\n"); + break; + + case ACPI_TRANSFER_8_16: + acpi_os_printf (" 8 and 16-bit transfer\n"); + break; + + case ACPI_TRANSFER_16: + acpi_os_printf (" 16 bit only transfer\n"); + break; + + default: + acpi_os_printf (" Invalid transfer preference\n"); + break; + } + + acpi_os_printf (" Number of Channels: %X ( ", dma_data->number_of_channels); + + for (index = 0; index < dma_data->number_of_channels; index++) { + acpi_os_printf ("%X ", dma_data->channels[index]); + } + + acpi_os_printf (")\n"); + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_start_depend_fns + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_start_depend_fns ( + union acpi_resource_data *data) +{ + struct acpi_resource_start_dpf *sdf_data = (struct acpi_resource_start_dpf *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("Start Dependent Functions Resource\n"); + + switch (sdf_data->compatibility_priority) { + case ACPI_GOOD_CONFIGURATION: + acpi_os_printf (" Good configuration\n"); + break; + + case ACPI_ACCEPTABLE_CONFIGURATION: + acpi_os_printf (" Acceptable configuration\n"); + break; + + case ACPI_SUB_OPTIMAL_CONFIGURATION: + acpi_os_printf (" Sub-optimal configuration\n"); + break; + + default: + acpi_os_printf (" Invalid compatibility priority\n"); + break; + } + + switch(sdf_data->performance_robustness) { + case ACPI_GOOD_CONFIGURATION: + acpi_os_printf (" Good configuration\n"); + break; + + case ACPI_ACCEPTABLE_CONFIGURATION: + acpi_os_printf (" Acceptable configuration\n"); + break; + + case ACPI_SUB_OPTIMAL_CONFIGURATION: + acpi_os_printf (" Sub-optimal configuration\n"); + break; + + default: + acpi_os_printf (" Invalid performance " + "robustness preference\n"); + break; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_io + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_io ( + union acpi_resource_data *data) +{ + struct acpi_resource_io *io_data = (struct acpi_resource_io *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("Io Resource\n"); + + acpi_os_printf (" %d bit decode\n", + ACPI_DECODE_16 == io_data->io_decode ? 16 : 10); + + acpi_os_printf (" Range minimum base: %08X\n", + io_data->min_base_address); + + acpi_os_printf (" Range maximum base: %08X\n", + io_data->max_base_address); + + acpi_os_printf (" Alignment: %08X\n", + io_data->alignment); + + acpi_os_printf (" Range Length: %08X\n", + io_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_fixed_io + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_fixed_io ( + union acpi_resource_data *data) +{ + struct acpi_resource_fixed_io *fixed_io_data = (struct acpi_resource_fixed_io *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("Fixed Io Resource\n"); + acpi_os_printf (" Range base address: %08X", + fixed_io_data->base_address); + + acpi_os_printf (" Range length: %08X", + fixed_io_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_vendor_specific + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_vendor_specific ( + union acpi_resource_data *data) +{ + struct acpi_resource_vendor *vendor_data = (struct acpi_resource_vendor *) data; + u16 index = 0; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("Vendor Specific Resource\n"); + + acpi_os_printf (" Length: %08X\n", vendor_data->length); + + for (index = 0; index < vendor_data->length; index++) { + acpi_os_printf (" Byte %X: %08X\n", + index, vendor_data->reserved[index]); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_memory24 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_memory24 ( + union acpi_resource_data *data) +{ + struct acpi_resource_mem24 *memory24_data = (struct acpi_resource_mem24 *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("24-Bit Memory Range Resource\n"); + + acpi_os_printf (" Read%s\n", + ACPI_READ_WRITE_MEMORY == + memory24_data->read_write_attribute ? + "/Write" : " only"); + + acpi_os_printf (" Range minimum base: %08X\n", + memory24_data->min_base_address); + + acpi_os_printf (" Range maximum base: %08X\n", + memory24_data->max_base_address); + + acpi_os_printf (" Alignment: %08X\n", + memory24_data->alignment); + + acpi_os_printf (" Range length: %08X\n", + memory24_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_memory32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_memory32 ( + union acpi_resource_data *data) +{ + struct acpi_resource_mem32 *memory32_data = (struct acpi_resource_mem32 *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("32-Bit Memory Range Resource\n"); + + acpi_os_printf (" Read%s\n", + ACPI_READ_WRITE_MEMORY == + memory32_data->read_write_attribute ? + "/Write" : " only"); + + acpi_os_printf (" Range minimum base: %08X\n", + memory32_data->min_base_address); + + acpi_os_printf (" Range maximum base: %08X\n", + memory32_data->max_base_address); + + acpi_os_printf (" Alignment: %08X\n", + memory32_data->alignment); + + acpi_os_printf (" Range length: %08X\n", + memory32_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_fixed_memory32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_fixed_memory32 ( + union acpi_resource_data *data) +{ + struct acpi_resource_fixed_mem32 *fixed_memory32_data = (struct acpi_resource_fixed_mem32 *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("32-Bit Fixed Location Memory Range Resource\n"); + + acpi_os_printf (" Read%s\n", + ACPI_READ_WRITE_MEMORY == + fixed_memory32_data->read_write_attribute ? + "/Write" : " Only"); + + acpi_os_printf (" Range base address: %08X\n", + fixed_memory32_data->range_base_address); + + acpi_os_printf (" Range length: %08X\n", + fixed_memory32_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_address16 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address16 ( + union acpi_resource_data *data) +{ + struct acpi_resource_address16 *address16_data = (struct acpi_resource_address16 *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("16-Bit Address Space Resource\n"); + acpi_os_printf (" Resource Type: "); + + switch (address16_data->resource_type) { + case ACPI_MEMORY_RANGE: + + acpi_os_printf ("Memory Range\n"); + + switch (address16_data->attribute.memory.cache_attribute) { + case ACPI_NON_CACHEABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Noncacheable memory\n"); + break; + + case ACPI_CACHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Cacheable memory\n"); + break; + + case ACPI_WRITE_COMBINING_MEMORY: + acpi_os_printf (" Type Specific: " + "Write-combining memory\n"); + break; + + case ACPI_PREFETCHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf (" Type Specific: Read%s\n", + ACPI_READ_WRITE_MEMORY == + address16_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case ACPI_IO_RANGE: + + acpi_os_printf ("I/O Range\n"); + + switch (address16_data->attribute.io.range_attribute) { + case ACPI_NON_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ACPI_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "ISA Io Addresses\n"); + break; + + case ACPI_ENTIRE_RANGE: + acpi_os_printf (" Type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid range attribute\n"); + break; + } + + acpi_os_printf (" Type Specific: %s Translation\n", + ACPI_SPARSE_TRANSLATION == + address16_data->attribute.io.translation_attribute ? + "Sparse" : "Dense"); + break; + + case ACPI_BUS_NUMBER_RANGE: + + acpi_os_printf ("Bus Number Range\n"); + break; + + default: + + acpi_os_printf ("0x%2.2X\n", address16_data->resource_type); + break; + } + + acpi_os_printf (" Resource %s\n", + ACPI_CONSUMER == address16_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf (" %s decode\n", + ACPI_SUB_DECODE == address16_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf (" Min address is %s fixed\n", + ACPI_ADDRESS_FIXED == address16_data->min_address_fixed ? + "" : "not"); + + acpi_os_printf (" Max address is %s fixed\n", + ACPI_ADDRESS_FIXED == address16_data->max_address_fixed ? + "" : "not"); + + acpi_os_printf (" Granularity: %08X\n", + address16_data->granularity); + + acpi_os_printf (" Address range min: %08X\n", + address16_data->min_address_range); + + acpi_os_printf (" Address range max: %08X\n", + address16_data->max_address_range); + + acpi_os_printf (" Address translation offset: %08X\n", + address16_data->address_translation_offset); + + acpi_os_printf (" Address Length: %08X\n", + address16_data->address_length); + + if (0xFF != address16_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X\n", + address16_data->resource_source.index); + acpi_os_printf (" Resource Source: %s\n", + address16_data->resource_source.string_ptr); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_address32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address32 ( + union acpi_resource_data *data) +{ + struct acpi_resource_address32 *address32_data = (struct acpi_resource_address32 *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("32-Bit Address Space Resource\n"); + + switch (address32_data->resource_type) { + case ACPI_MEMORY_RANGE: + + acpi_os_printf (" Resource Type: Memory Range\n"); + + switch (address32_data->attribute.memory.cache_attribute) { + case ACPI_NON_CACHEABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Noncacheable memory\n"); + break; + + case ACPI_CACHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Cacheable memory\n"); + break; + + case ACPI_WRITE_COMBINING_MEMORY: + acpi_os_printf (" Type Specific: " + "Write-combining memory\n"); + break; + + case ACPI_PREFETCHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf (" Type Specific: Read%s\n", + ACPI_READ_WRITE_MEMORY == + address32_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case ACPI_IO_RANGE: + + acpi_os_printf (" Resource Type: Io Range\n"); + + switch (address32_data->attribute.io.range_attribute) { + case ACPI_NON_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ACPI_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "ISA Io Addresses\n"); + break; + + case ACPI_ENTIRE_RANGE: + acpi_os_printf (" Type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid Range attribute"); + break; + } + + acpi_os_printf (" Type Specific: %s Translation\n", + ACPI_SPARSE_TRANSLATION == + address32_data->attribute.io.translation_attribute ? + "Sparse" : "Dense"); + break; + + case ACPI_BUS_NUMBER_RANGE: + + acpi_os_printf (" Resource Type: Bus Number Range\n"); + break; + + default: + + acpi_os_printf (" Resource Type: 0x%2.2X\n", address32_data->resource_type); + break; + } + + acpi_os_printf (" Resource %s\n", + ACPI_CONSUMER == address32_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf (" %s decode\n", + ACPI_SUB_DECODE == address32_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf (" Min address is %s fixed\n", + ACPI_ADDRESS_FIXED == address32_data->min_address_fixed ? + "" : "not "); + + acpi_os_printf (" Max address is %s fixed\n", + ACPI_ADDRESS_FIXED == address32_data->max_address_fixed ? + "" : "not "); + + acpi_os_printf (" Granularity: %08X\n", + address32_data->granularity); + + acpi_os_printf (" Address range min: %08X\n", + address32_data->min_address_range); + + acpi_os_printf (" Address range max: %08X\n", + address32_data->max_address_range); + + acpi_os_printf (" Address translation offset: %08X\n", + address32_data->address_translation_offset); + + acpi_os_printf (" Address Length: %08X\n", + address32_data->address_length); + + if(0xFF != address32_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X\n", + address32_data->resource_source.index); + acpi_os_printf (" Resource Source: %s\n", + address32_data->resource_source.string_ptr); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_address64 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address64 ( + union acpi_resource_data *data) +{ + struct acpi_resource_address64 *address64_data = (struct acpi_resource_address64 *) data; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("64-Bit Address Space Resource\n"); + + switch (address64_data->resource_type) { + case ACPI_MEMORY_RANGE: + + acpi_os_printf (" Resource Type: Memory Range\n"); + + switch (address64_data->attribute.memory.cache_attribute) { + case ACPI_NON_CACHEABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Noncacheable memory\n"); + break; + + case ACPI_CACHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Cacheable memory\n"); + break; + + case ACPI_WRITE_COMBINING_MEMORY: + acpi_os_printf (" Type Specific: " + "Write-combining memory\n"); + break; + + case ACPI_PREFETCHABLE_MEMORY: + acpi_os_printf (" Type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf (" Type Specific: Read%s\n", + ACPI_READ_WRITE_MEMORY == + address64_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case ACPI_IO_RANGE: + + acpi_os_printf (" Resource Type: Io Range\n"); + + switch (address64_data->attribute.io.range_attribute) { + case ACPI_NON_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ACPI_ISA_ONLY_RANGES: + acpi_os_printf (" Type Specific: " + "ISA Io Addresses\n"); + break; + + case ACPI_ENTIRE_RANGE: + acpi_os_printf (" Type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf (" Type Specific: " + "Invalid Range attribute"); + break; + } + + acpi_os_printf (" Type Specific: %s Translation\n", + ACPI_SPARSE_TRANSLATION == + address64_data->attribute.io.translation_attribute ? + "Sparse" : "Dense"); + break; + + case ACPI_BUS_NUMBER_RANGE: + + acpi_os_printf (" Resource Type: Bus Number Range\n"); + break; + + default: + + acpi_os_printf (" Resource Type: 0x%2.2X\n", address64_data->resource_type); + break; + } + + acpi_os_printf (" Resource %s\n", + ACPI_CONSUMER == address64_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf (" %s decode\n", + ACPI_SUB_DECODE == address64_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf (" Min address is %s fixed\n", + ACPI_ADDRESS_FIXED == address64_data->min_address_fixed ? + "" : "not "); + + acpi_os_printf (" Max address is %s fixed\n", + ACPI_ADDRESS_FIXED == address64_data->max_address_fixed ? + "" : "not "); + + acpi_os_printf (" Granularity: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->granularity)); + + acpi_os_printf (" Address range min: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->min_address_range)); + + acpi_os_printf (" Address range max: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->max_address_range)); + + acpi_os_printf (" Address translation offset: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->address_translation_offset)); + + acpi_os_printf (" Address Length: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->address_length)); + + acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes)); + + if (0xFF != address64_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X\n", + address64_data->resource_source.index); + acpi_os_printf (" Resource Source: %s\n", + address64_data->resource_source.string_ptr); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_extended_irq + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_extended_irq ( + union acpi_resource_data *data) +{ + struct acpi_resource_ext_irq *ext_irq_data = (struct acpi_resource_ext_irq *) data; + u8 index = 0; + + + ACPI_FUNCTION_ENTRY (); + + + acpi_os_printf ("Extended IRQ Resource\n"); + + acpi_os_printf (" Resource %s\n", + ACPI_CONSUMER == ext_irq_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf (" %s\n", + ACPI_LEVEL_SENSITIVE == ext_irq_data->edge_level ? + "Level" : "Edge"); + + acpi_os_printf (" Active %s\n", + ACPI_ACTIVE_LOW == ext_irq_data->active_high_low ? + "low" : "high"); + + acpi_os_printf (" %s\n", + ACPI_SHARED == ext_irq_data->shared_exclusive ? + "Shared" : "Exclusive"); + + acpi_os_printf (" Interrupts : %X ( ", + ext_irq_data->number_of_interrupts); + + for (index = 0; index < ext_irq_data->number_of_interrupts; index++) { + acpi_os_printf ("%X ", ext_irq_data->interrupts[index]); + } + + acpi_os_printf (")\n"); + + if(0xFF != ext_irq_data->resource_source.index) { + acpi_os_printf (" Resource Source Index: %X", + ext_irq_data->resource_source.index); + acpi_os_printf (" Resource Source: %s", + ext_irq_data->resource_source.string_ptr); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_resource_list + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: None + * + * DESCRIPTION: Dispatches the structure to the correct dump routine. + * + ******************************************************************************/ + +void +acpi_rs_dump_resource_list ( + struct acpi_resource *resource) +{ + u8 count = 0; + u8 done = FALSE; + + + ACPI_FUNCTION_ENTRY (); + + + if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) { + while (!done) { + acpi_os_printf ("Resource structure %X.\n", count++); + + switch (resource->id) { + case ACPI_RSTYPE_IRQ: + acpi_rs_dump_irq (&resource->data); + break; + + case ACPI_RSTYPE_DMA: + acpi_rs_dump_dma (&resource->data); + break; + + case ACPI_RSTYPE_START_DPF: + acpi_rs_dump_start_depend_fns (&resource->data); + break; + + case ACPI_RSTYPE_END_DPF: + acpi_os_printf ("end_dependent_functions Resource\n"); + /* acpi_rs_dump_end_dependent_functions (Resource->Data);*/ + break; + + case ACPI_RSTYPE_IO: + acpi_rs_dump_io (&resource->data); + break; + + case ACPI_RSTYPE_FIXED_IO: + acpi_rs_dump_fixed_io (&resource->data); + break; + + case ACPI_RSTYPE_VENDOR: + acpi_rs_dump_vendor_specific (&resource->data); + break; + + case ACPI_RSTYPE_END_TAG: + /*rs_dump_end_tag (Resource->Data);*/ + acpi_os_printf ("end_tag Resource\n"); + done = TRUE; + break; + + case ACPI_RSTYPE_MEM24: + acpi_rs_dump_memory24 (&resource->data); + break; + + case ACPI_RSTYPE_MEM32: + acpi_rs_dump_memory32 (&resource->data); + break; + + case ACPI_RSTYPE_FIXED_MEM32: + acpi_rs_dump_fixed_memory32 (&resource->data); + break; + + case ACPI_RSTYPE_ADDRESS16: + acpi_rs_dump_address16 (&resource->data); + break; + + case ACPI_RSTYPE_ADDRESS32: + acpi_rs_dump_address32 (&resource->data); + break; + + case ACPI_RSTYPE_ADDRESS64: + acpi_rs_dump_address64 (&resource->data); + break; + + case ACPI_RSTYPE_EXT_IRQ: + acpi_rs_dump_extended_irq (&resource->data); + break; + + default: + acpi_os_printf ("Invalid resource type\n"); + break; + + } + + resource = ACPI_PTR_ADD (struct acpi_resource, resource, resource->length); + } + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dump_irq_list + * + * PARAMETERS: Data - pointer to the routing table to dump. + * + * RETURN: None + * + * DESCRIPTION: Dispatches the structures to the correct dump routine. + * + ******************************************************************************/ + +void +acpi_rs_dump_irq_list ( + u8 *route_table) +{ + u8 *buffer = route_table; + u8 count = 0; + u8 done = FALSE; + struct acpi_pci_routing_table *prt_element; + + + ACPI_FUNCTION_ENTRY (); + + + if (acpi_dbg_level & ACPI_LV_RESOURCES && _COMPONENT & acpi_dbg_layer) { + prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer); + + while (!done) { + acpi_os_printf ("PCI IRQ Routing Table structure %X.\n", count++); + + acpi_os_printf (" Address: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (prt_element->address)); + + acpi_os_printf (" Pin: %X\n", prt_element->pin); + + acpi_os_printf (" Source: %s\n", prt_element->source); + + acpi_os_printf (" source_index: %X\n", + prt_element->source_index); + + buffer += prt_element->length; + + prt_element = ACPI_CAST_PTR (struct acpi_pci_routing_table, buffer); + + if(0 == prt_element->length) { + done = TRUE; + } + } + } + + return; +} + +#endif + diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c new file mode 100644 index 000000000000..972c746d37e4 --- /dev/null +++ b/drivers/acpi/resources/rsio.c @@ -0,0 +1,545 @@ +/******************************************************************************* + * + * Module Name: rsio - IO and DMA resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsio") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_io_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_io_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io); + + + ACPI_FUNCTION_TRACE ("rs_io_resource"); + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 8; + + output_struct->id = ACPI_RSTYPE_IO; + + /* + * Check Decode + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.io.io_decode = temp8 & 0x01; + + /* + * Check min_base Address + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + output_struct->data.io.min_base_address = temp16; + + /* + * Check max_base Address + */ + buffer += 2; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + output_struct->data.io.max_base_address = temp16; + + /* + * Check Base alignment + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.io.alignment = temp8; + + /* + * Check range_length + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.io.range_length = temp8; + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_fixed_io_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_fixed_io_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io); + + + ACPI_FUNCTION_TRACE ("rs_fixed_io_resource"); + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 4; + + output_struct->id = ACPI_RSTYPE_FIXED_IO; + + /* + * Check Range Base Address + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + output_struct->data.fixed_io.base_address = temp16; + + /* + * Check range_length + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.fixed_io.range_length = temp8; + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_io_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_io_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_io_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x47; + buffer += 1; + + /* + * Io Information Byte + */ + temp8 = (u8) (linked_list->data.io.io_decode & 0x01); + + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + temp16 = (u16) linked_list->data.io.min_base_address; + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Range maximum base address + */ + temp16 = (u16) linked_list->data.io.max_base_address; + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the base alignment + */ + temp8 = (u8) linked_list->data.io.alignment; + + *buffer = temp8; + buffer += 1; + + /* + * Set the range length + */ + temp8 = (u8) linked_list->data.io.range_length; + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_fixed_io_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_fixed_io_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_fixed_io_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x4B; + + buffer += 1; + + /* + * Set the Range base address + */ + temp16 = (u16) linked_list->data.fixed_io.base_address; + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the range length + */ + temp8 = (u8) linked_list->data.fixed_io.range_length; + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dma_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_dma_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u8 temp8 = 0; + u8 index; + u8 i; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma); + + + ACPI_FUNCTION_TRACE ("rs_dma_resource"); + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 3; + output_struct->id = ACPI_RSTYPE_DMA; + + /* + * Point to the 8-bits of Byte 1 + */ + buffer += 1; + temp8 = *buffer; + + /* Decode the DMA channel bits */ + + for (i = 0, index = 0; index < 8; index++) { + if ((temp8 >> index) & 0x01) { + output_struct->data.dma.channels[i] = index; + i++; + } + } + + /* Zero DMA channels is valid */ + + output_struct->data.dma.number_of_channels = i; + if (i > 0) { + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += ((acpi_size) i - 1) * 4; + } + + /* + * Point to Byte 2 + */ + buffer += 1; + temp8 = *buffer; + + /* + * Check for transfer preference (Bits[1:0]) + */ + output_struct->data.dma.transfer = temp8 & 0x03; + + if (0x03 == output_struct->data.dma.transfer) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid DMA.Transfer preference (3)\n")); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* + * Get bus master preference (Bit[2]) + */ + output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01; + + /* + * Get channel speed support (Bits[6:5]) + */ + output_struct->data.dma.type = (temp8 >> 5) & 0x03; + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_dma_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_dma_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + + + ACPI_FUNCTION_TRACE ("rs_dma_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x2A; + buffer += 1; + temp8 = 0; + + /* + * Loop through all of the Channels and set the mask bits + */ + for (index = 0; + index < linked_list->data.dma.number_of_channels; + index++) { + temp16 = (u16) linked_list->data.dma.channels[index]; + temp8 |= 0x1 << temp16; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the DMA Info + */ + temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5); + temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2); + temp8 |= (linked_list->data.dma.transfer & 0x03); + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c new file mode 100644 index 000000000000..fd07a8702fbe --- /dev/null +++ b/drivers/acpi/resources/rsirq.c @@ -0,0 +1,592 @@ +/******************************************************************************* + * + * Module Name: rsirq - IRQ resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsirq") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_irq_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_irq_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u8 i; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_irq); + + + ACPI_FUNCTION_TRACE ("rs_irq_resource"); + + + /* + * The number of bytes consumed are contained in the descriptor + * (Bits:0-1) + */ + temp8 = *buffer; + *bytes_consumed = (temp8 & 0x03) + 1; + output_struct->id = ACPI_RSTYPE_IRQ; + + /* + * Point to the 16-bits of Bytes 1 and 2 + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + output_struct->data.irq.number_of_interrupts = 0; + + /* Decode the IRQ bits */ + + for (i = 0, index = 0; index < 16; index++) { + if ((temp16 >> index) & 0x01) { + output_struct->data.irq.interrupts[i] = index; + i++; + } + } + + /* Zero interrupts is valid */ + + output_struct->data.irq.number_of_interrupts = i; + if (i > 0) { + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += ((acpi_size) i - 1) * 4; + } + + /* + * Point to Byte 3 if it is used + */ + if (4 == *bytes_consumed) { + buffer += 2; + temp8 = *buffer; + + /* + * Check for HE, LL interrupts + */ + switch (temp8 & 0x09) { + case 0x01: /* HE */ + output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE; + output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH; + break; + + case 0x08: /* LL */ + output_struct->data.irq.edge_level = ACPI_LEVEL_SENSITIVE; + output_struct->data.irq.active_high_low = ACPI_ACTIVE_LOW; + break; + + default: + /* + * Only _LL and _HE polarity/trigger interrupts + * are allowed (ACPI spec, section "IRQ Format") + * so 0x00 and 0x09 are illegal. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Invalid interrupt polarity/trigger in resource list, %X\n", temp8)); + return_ACPI_STATUS (AE_BAD_DATA); + } + + /* + * Check for sharable + */ + output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01; + } + else { + /* + * Assume Edge Sensitive, Active High, Non-Sharable + * per ACPI Specification + */ + output_struct->data.irq.edge_level = ACPI_EDGE_SENSITIVE; + output_struct->data.irq.active_high_low = ACPI_ACTIVE_HIGH; + output_struct->data.irq.shared_exclusive = ACPI_EXCLUSIVE; + } + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_irq_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_irq_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u8 IRqinfo_byte_needed; + + + ACPI_FUNCTION_TRACE ("rs_irq_stream"); + + + /* + * The descriptor field is set based upon whether a third byte is + * needed to contain the IRQ Information. + */ + if (ACPI_EDGE_SENSITIVE == linked_list->data.irq.edge_level && + ACPI_ACTIVE_HIGH == linked_list->data.irq.active_high_low && + ACPI_EXCLUSIVE == linked_list->data.irq.shared_exclusive) { + *buffer = 0x22; + IRqinfo_byte_needed = FALSE; + } + else { + *buffer = 0x23; + IRqinfo_byte_needed = TRUE; + } + + buffer += 1; + temp16 = 0; + + /* + * Loop through all of the interrupts and set the mask bits + */ + for(index = 0; + index < linked_list->data.irq.number_of_interrupts; + index++) { + temp8 = (u8) linked_list->data.irq.interrupts[index]; + temp16 |= 0x1 << temp8; + } + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the IRQ Info byte if needed. + */ + if (IRqinfo_byte_needed) { + temp8 = 0; + temp8 = (u8) ((linked_list->data.irq.shared_exclusive & + 0x01) << 4); + + if (ACPI_LEVEL_SENSITIVE == linked_list->data.irq.edge_level && + ACPI_ACTIVE_LOW == linked_list->data.irq.active_high_low) { + temp8 |= 0x08; + } + else { + temp8 |= 0x01; + } + + *buffer = temp8; + buffer += 1; + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_extended_irq_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_extended_irq_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 *temp_ptr; + u8 index; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq); + + + ACPI_FUNCTION_TRACE ("rs_extended_irq_resource"); + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + /* Validate minimum descriptor length */ + + if (temp16 < 6) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + *bytes_consumed = temp16 + 3; + output_struct->id = ACPI_RSTYPE_EXT_IRQ; + + /* + * Point to the Byte3 + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.extended_irq.producer_consumer = temp8 & 0x01; + + /* + * Check for Interrupt Mode + * + * The definition of an Extended IRQ changed between ACPI spec v1.0b + * and ACPI spec 2.0 (section 6.4.3.6 in both). + * + * - Edge/Level are defined opposite in the table vs the headers + */ + output_struct->data.extended_irq.edge_level = + (temp8 & 0x2) ? ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE; + + /* + * Check Interrupt Polarity + */ + output_struct->data.extended_irq.active_high_low = (temp8 >> 2) & 0x1; + + /* + * Check for sharable + */ + output_struct->data.extended_irq.shared_exclusive = (temp8 >> 3) & 0x01; + + /* + * Point to Byte4 (IRQ Table length) + */ + buffer += 1; + temp8 = *buffer; + + /* Must have at least one IRQ */ + + if (temp8 < 1) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + output_struct->data.extended_irq.number_of_interrupts = temp8; + + /* + * Add any additional structure size to properly calculate + * the next pointer at the end of this function + */ + struct_size += (temp8 - 1) * 4; + + /* + * Point to Byte5 (First IRQ Number) + */ + buffer += 1; + + /* + * Cycle through every IRQ in the table + */ + for (index = 0; index < temp8; index++) { + ACPI_MOVE_32_TO_32 ( + &output_struct->data.extended_irq.interrupts[index], buffer); + + /* Point to the next IRQ */ + + buffer += 4; + } + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the length. + */ + if (*bytes_consumed > + ((acpi_size) output_struct->data.extended_irq.number_of_interrupts * 4) + (5 + 1)) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.extended_irq.resource_source.index = (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* + * Point the String pointer to the end of this structure. + */ + output_struct->data.extended_irq.resource_source.string_ptr = + (char *)((char *) output_struct + struct_size); + + temp_ptr = (u8 *) output_struct->data.extended_irq.resource_source.string_ptr; + + /* Copy the string into the buffer */ + + index = 0; + while (0x00 != *buffer) { + *temp_ptr = *buffer; + + temp_ptr += 1; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + *temp_ptr = 0x00; + output_struct->data.extended_irq.resource_source.string_length = index + 1; + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + temp8 = (u8) (index + 1); + struct_size += ACPI_ROUND_UP_to_32_bITS (temp8); + } + else { + output_struct->data.extended_irq.resource_source.index = 0x00; + output_struct->data.extended_irq.resource_source.string_length = 0; + output_struct->data.extended_irq.resource_source.string_ptr = NULL; + } + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_extended_irq_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_extended_irq_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 *length_field; + u8 temp8 = 0; + u8 index; + char *temp_pointer = NULL; + + + ACPI_FUNCTION_TRACE ("rs_extended_irq_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x89; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + length_field = ACPI_CAST_PTR (u16, buffer); + buffer += 2; + + /* + * Set the Interrupt vector flags + */ + temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01); + temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3); + + /* + * Set the Interrupt Mode + * + * The definition of an Extended IRQ changed between ACPI spec v1.0b + * and ACPI spec 2.0 (section 6.4.3.6 in both). This code does not + * implement the more restrictive definition of 1.0b + * + * - Edge/Level are defined opposite in the table vs the headers + */ + if (ACPI_EDGE_SENSITIVE == linked_list->data.extended_irq.edge_level) { + temp8 |= 0x2; + } + + /* + * Set the Interrupt Polarity + */ + temp8 |= ((linked_list->data.extended_irq.active_high_low & 0x1) << 2); + + *buffer = temp8; + buffer += 1; + + /* + * Set the Interrupt table length + */ + temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts; + + *buffer = temp8; + buffer += 1; + + for (index = 0; index < linked_list->data.extended_irq.number_of_interrupts; + index++) { + ACPI_MOVE_32_TO_32 (buffer, + &linked_list->data.extended_irq.interrupts[index]); + buffer += 4; + } + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.extended_irq.resource_source.string_length) { + *buffer = (u8) linked_list->data.extended_irq.resource_source.index; + buffer += 1; + + temp_pointer = (char *) buffer; + + /* + * Copy the string + */ + ACPI_STRCPY (temp_pointer, + linked_list->data.extended_irq.resource_source.string_ptr); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (acpi_size)(ACPI_STRLEN (linked_list->data.extended_irq.resource_source.string_ptr) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c new file mode 100644 index 000000000000..e49c1e030f99 --- /dev/null +++ b/drivers/acpi/resources/rslist.c @@ -0,0 +1,518 @@ +/******************************************************************************* + * + * Module Name: rslist - Linked list utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rslist") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_type + * + * PARAMETERS: resource_start_byte - Byte 0 of a resource descriptor + * + * RETURN: The Resource Type (Name) with no extraneous bits + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +u8 +acpi_rs_get_resource_type ( + u8 resource_start_byte) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* + * Determine if this is a small or large resource + */ + switch (resource_start_byte & ACPI_RDESC_TYPE_MASK) { + case ACPI_RDESC_TYPE_SMALL: + + /* + * Small Resource Type -- Only bits 6:3 are valid + */ + return ((u8) (resource_start_byte & ACPI_RDESC_SMALL_MASK)); + + + case ACPI_RDESC_TYPE_LARGE: + + /* + * Large Resource Type -- All bits are valid + */ + return (resource_start_byte); + + + default: + /* No other types of resource descriptor */ + break; + } + + return (0xFF); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_byte_stream_to_list + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource byte stream + * byte_stream_buffer_length - Length of byte_stream_buffer + * output_buffer - Pointer to the buffer that will + * contain the output structures + * + * RETURN: Status + * + * DESCRIPTION: Takes the resource byte stream and parses it, creating a + * linked list of resources in the caller's output buffer + * + ******************************************************************************/ + +acpi_status +acpi_rs_byte_stream_to_list ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u8 *output_buffer) +{ + acpi_status status; + acpi_size bytes_parsed = 0; + u8 resource_type = 0; + acpi_size bytes_consumed = 0; + u8 *buffer = output_buffer; + acpi_size structure_size = 0; + u8 end_tag_processed = FALSE; + struct acpi_resource *resource; + + ACPI_FUNCTION_TRACE ("rs_byte_stream_to_list"); + + + while (bytes_parsed < byte_stream_buffer_length && + !end_tag_processed) { + /* + * The next byte in the stream is the resource type + */ + resource_type = acpi_rs_get_resource_type (*byte_stream_buffer); + + switch (resource_type) { + case ACPI_RDESC_TYPE_MEMORY_24: + /* + * 24-Bit Memory Resource + */ + status = acpi_rs_memory24_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_LARGE_VENDOR: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_MEMORY_32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_FIXED_MEMORY_32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE: + case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE: + /* + * 64-Bit Address Resource + */ + status = acpi_rs_address64_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + status = acpi_rs_address32_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + status = acpi_rs_address16_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_EXTENDED_XRUPT: + /* + * Extended IRQ + */ + status = acpi_rs_extended_irq_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_IRQ_FORMAT: + /* + * IRQ Resource + */ + status = acpi_rs_irq_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_DMA_FORMAT: + /* + * DMA Resource + */ + status = acpi_rs_dma_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_START_DEPENDENT: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_depend_fns_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_END_DEPENDENT: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_depend_fns_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_IO_PORT: + /* + * IO Port Resource + */ + status = acpi_rs_io_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_FIXED_IO_PORT: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_SMALL_VENDOR: + /* + * Vendor Specific Resource + */ + status = acpi_rs_vendor_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + case ACPI_RDESC_TYPE_END_TAG: + /* + * End Tag + */ + end_tag_processed = TRUE; + status = acpi_rs_end_tag_resource (byte_stream_buffer, + &bytes_consumed, &buffer, &structure_size); + break; + + + default: + /* + * Invalid/Unknown resource type + */ + status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } + + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Update the return value and counter + */ + bytes_parsed += bytes_consumed; + + /* + * Set the byte stream to point to the next resource + */ + byte_stream_buffer += bytes_consumed; + + /* + * Set the Buffer to the next structure + */ + resource = ACPI_CAST_PTR (struct acpi_resource, buffer); + resource->length = (u32) ACPI_ALIGN_RESOURCE_SIZE (resource->length); + buffer += ACPI_ALIGN_RESOURCE_SIZE (structure_size); + + } /* end while */ + + /* + * Check the reason for exiting the while loop + */ + if (!end_tag_processed) { + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_list_to_byte_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * byte_steam_size_needed - Calculated size of the byte stream + * needed from calling + * acpi_rs_get_byte_stream_length() + * The size of the output_buffer is + * guaranteed to be >= + * byte_stream_size_needed + * output_buffer - Pointer to the buffer that will + * contain the byte stream + * + * RETURN: Status + * + * DESCRIPTION: Takes the resource linked list and parses it, creating a + * byte stream of resources in the caller's output buffer + * + ******************************************************************************/ + +acpi_status +acpi_rs_list_to_byte_stream ( + struct acpi_resource *linked_list, + acpi_size byte_stream_size_needed, + u8 *output_buffer) +{ + acpi_status status; + u8 *buffer = output_buffer; + acpi_size bytes_consumed = 0; + u8 done = FALSE; + + + ACPI_FUNCTION_TRACE ("rs_list_to_byte_stream"); + + + while (!done) { + switch (linked_list->id) { + case ACPI_RSTYPE_IRQ: + /* + * IRQ Resource + */ + status = acpi_rs_irq_stream (linked_list, &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_DMA: + /* + * DMA Resource + */ + status = acpi_rs_dma_stream (linked_list, &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_START_DPF: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_depend_fns_stream (linked_list, + &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_END_DPF: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_depend_fns_stream (linked_list, + &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_IO: + /* + * IO Port Resource + */ + status = acpi_rs_io_stream (linked_list, &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_FIXED_IO: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_stream (linked_list, &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_VENDOR: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_stream (linked_list, &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_END_TAG: + /* + * End Tag + */ + status = acpi_rs_end_tag_stream (linked_list, &buffer, &bytes_consumed); + + /* + * An End Tag indicates the end of the Resource Template + */ + done = TRUE; + break; + + case ACPI_RSTYPE_MEM24: + /* + * 24-Bit Memory Resource + */ + status = acpi_rs_memory24_stream (linked_list, &buffer, &bytes_consumed); + break; + + case ACPI_RSTYPE_MEM32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_stream (linked_list, &buffer, + &bytes_consumed); + break; + + case ACPI_RSTYPE_FIXED_MEM32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_stream (linked_list, &buffer, + &bytes_consumed); + break; + + case ACPI_RSTYPE_ADDRESS16: + /* + * 16-Bit Address Descriptor Resource + */ + status = acpi_rs_address16_stream (linked_list, &buffer, + &bytes_consumed); + break; + + case ACPI_RSTYPE_ADDRESS32: + /* + * 32-Bit Address Descriptor Resource + */ + status = acpi_rs_address32_stream (linked_list, &buffer, + &bytes_consumed); + break; + + case ACPI_RSTYPE_ADDRESS64: + /* + * 64-Bit Address Descriptor Resource + */ + status = acpi_rs_address64_stream (linked_list, &buffer, + &bytes_consumed); + break; + + case ACPI_RSTYPE_EXT_IRQ: + /* + * Extended IRQ Resource + */ + status = acpi_rs_extended_irq_stream (linked_list, &buffer, + &bytes_consumed); + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid descriptor type (%X) in resource list\n", + linked_list->id)); + status = AE_BAD_DATA; + break; + + } /* switch (linked_list->Id) */ + + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Set the Buffer to point to the open byte + */ + buffer += bytes_consumed; + + /* + * Point to the next object + */ + linked_list = ACPI_PTR_ADD (struct acpi_resource, + linked_list, linked_list->length); + } + + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c new file mode 100644 index 000000000000..7c935aecf075 --- /dev/null +++ b/drivers/acpi/resources/rsmemory.c @@ -0,0 +1,566 @@ +/******************************************************************************* + * + * Module Name: rsmem24 - Memory resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsmemory") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_memory24_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_memory24_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24); + + + ACPI_FUNCTION_TRACE ("rs_memory24_resource"); + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + ACPI_MOVE_16_TO_16 (&temp16, buffer); + buffer += 2; + *bytes_consumed = (acpi_size) temp16 + 3; + output_struct->id = ACPI_RSTYPE_MEM24; + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + output_struct->data.memory24.read_write_attribute = temp8 & 0x01; + + /* + * Get min_base_address (Bytes 4-5) + */ + ACPI_MOVE_16_TO_16 (&temp16, buffer); + buffer += 2; + output_struct->data.memory24.min_base_address = temp16; + + /* + * Get max_base_address (Bytes 6-7) + */ + ACPI_MOVE_16_TO_16 (&temp16, buffer); + buffer += 2; + output_struct->data.memory24.max_base_address = temp16; + + /* + * Get Alignment (Bytes 8-9) + */ + ACPI_MOVE_16_TO_16 (&temp16, buffer); + buffer += 2; + output_struct->data.memory24.alignment = temp16; + + /* + * Get range_length (Bytes 10-11) + */ + ACPI_MOVE_16_TO_16 (&temp16, buffer); + output_struct->data.memory24.range_length = temp16; + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_memory24_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_memory24_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_memory24_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x81; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x09; + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.min_base_address); + buffer += 2; + + /* + * Set the Range maximum base address + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.max_base_address); + buffer += 2; + + /* + * Set the base alignment + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.alignment); + buffer += 2; + + /* + * Set the range length + */ + ACPI_MOVE_32_TO_16 (buffer, &linked_list->data.memory24.range_length); + buffer += 2; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_memory32_range_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_memory32_range_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32); + + + ACPI_FUNCTION_TRACE ("rs_memory32_range_resource"); + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + ACPI_MOVE_16_TO_16 (&temp16, buffer); + buffer += 2; + *bytes_consumed = (acpi_size) temp16 + 3; + + output_struct->id = ACPI_RSTYPE_MEM32; + + /* + * Point to the place in the output buffer where the data portion will + * begin. + * 1. Set the RESOURCE_DATA * Data to point to its own address, then + * 2. Set the pointer to the next address. + * + * NOTE: output_struct->Data is cast to u8, otherwise, this addition adds + * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8) + */ + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + + output_struct->data.memory32.read_write_attribute = temp8 & 0x01; + + /* + * Get min_base_address (Bytes 4-7) + */ + ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.min_base_address, buffer); + buffer += 4; + + /* + * Get max_base_address (Bytes 8-11) + */ + ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.max_base_address, buffer); + buffer += 4; + + /* + * Get Alignment (Bytes 12-15) + */ + ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.alignment, buffer); + buffer += 4; + + /* + * Get range_length (Bytes 16-19) + */ + ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.range_length, buffer); + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_fixed_memory32_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_fixed_memory32_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32); + + + ACPI_FUNCTION_TRACE ("rs_fixed_memory32_resource"); + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + buffer += 2; + *bytes_consumed = (acpi_size) temp16 + 3; + + output_struct->id = ACPI_RSTYPE_FIXED_MEM32; + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01; + + /* + * Get range_base_address (Bytes 4-7) + */ + ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_base_address, buffer); + buffer += 4; + + /* + * Get range_length (Bytes 8-11) + */ + ACPI_MOVE_32_TO_32 (&output_struct->data.fixed_memory32.range_length, buffer); + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_memory32_range_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_memory32_range_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_memory32_range_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x85; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x11; + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.min_base_address); + buffer += 4; + + /* + * Set the Range maximum base address + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.max_base_address); + buffer += 4; + + /* + * Set the base alignment + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.alignment); + buffer += 4; + + /* + * Set the range length + */ + ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.range_length); + buffer += 4; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_fixed_memory32_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_fixed_memory32_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_fixed_memory32_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x86; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x09; + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range base address + */ + ACPI_MOVE_32_TO_32 (buffer, + &linked_list->data.fixed_memory32.range_base_address); + buffer += 4; + + /* + * Set the range length + */ + ACPI_MOVE_32_TO_32 (buffer, + &linked_list->data.fixed_memory32.range_length); + buffer += 4; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c new file mode 100644 index 000000000000..d16be44b5df7 --- /dev/null +++ b/drivers/acpi/resources/rsmisc.c @@ -0,0 +1,597 @@ +/******************************************************************************* + * + * Module Name: rsmisc - Miscellaneous resource descriptors + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsmisc") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_end_tag_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_end_tag_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + struct acpi_resource *output_struct = (void *) *output_buffer; + acpi_size struct_size = ACPI_RESOURCE_LENGTH; + + + ACPI_FUNCTION_TRACE ("rs_end_tag_resource"); + + + /* + * The number of bytes consumed is static + */ + *bytes_consumed = 2; + + /* + * Fill out the structure + */ + output_struct->id = ACPI_RSTYPE_END_TAG; + + /* + * Set the Length parameter + */ + output_struct->length = 0; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_end_tag_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_end_tag_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_end_tag_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x79; + buffer += 1; + + /* + * Set the Checksum - zero means that the resource data is treated as if + * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8) + */ + temp8 = 0; + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_vendor_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_vendor_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor); + + + ACPI_FUNCTION_TRACE ("rs_vendor_resource"); + + + /* + * Dereference the Descriptor to find if this is a large or small item. + */ + temp8 = *buffer; + + if (temp8 & 0x80) { + /* + * Large Item, point to the length field + */ + buffer += 1; + + /* Dereference */ + + ACPI_MOVE_16_TO_16 (&temp16, buffer); + + /* Calculate bytes consumed */ + + *bytes_consumed = (acpi_size) temp16 + 3; + + /* Point to the first vendor byte */ + + buffer += 2; + } + else { + /* + * Small Item, dereference the size + */ + temp16 = (u8)(*buffer & 0x07); + + /* Calculate bytes consumed */ + + *bytes_consumed = (acpi_size) temp16 + 1; + + /* Point to the first vendor byte */ + + buffer += 1; + } + + output_struct->id = ACPI_RSTYPE_VENDOR; + output_struct->data.vendor_specific.length = temp16; + + for (index = 0; index < temp16; index++) { + output_struct->data.vendor_specific.reserved[index] = *buffer; + buffer += 1; + } + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the vendor string and expand the + * struct_size to the next 32-bit boundary. + */ + struct_size += ACPI_ROUND_UP_to_32_bITS (temp16); + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_vendor_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_vendor_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + + + ACPI_FUNCTION_TRACE ("rs_vendor_stream"); + + + /* + * Dereference the length to find if this is a large or small item. + */ + if(linked_list->data.vendor_specific.length > 7) { + /* + * Large Item, Set the descriptor field and length bytes + */ + *buffer = 0x84; + buffer += 1; + + temp16 = (u16) linked_list->data.vendor_specific.length; + + ACPI_MOVE_16_TO_16 (buffer, &temp16); + buffer += 2; + } + else { + /* + * Small Item, Set the descriptor field + */ + temp8 = 0x70; + temp8 |= (u8) linked_list->data.vendor_specific.length; + + *buffer = temp8; + buffer += 1; + } + + /* + * Loop through all of the Vendor Specific fields + */ + for (index = 0; index < linked_list->data.vendor_specific.length; index++) { + temp8 = linked_list->data.vendor_specific.reserved[index]; + + *buffer = temp8; + buffer += 1; + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_start_depend_fns_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_start_depend_fns_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + u8 *buffer = byte_stream_buffer; + struct acpi_resource *output_struct = (void *) *output_buffer; + u8 temp8 = 0; + acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf); + + + ACPI_FUNCTION_TRACE ("rs_start_depend_fns_resource"); + + + /* + * The number of bytes consumed are contained in the descriptor (Bits:0-1) + */ + temp8 = *buffer; + + *bytes_consumed = (temp8 & 0x01) + 1; + + output_struct->id = ACPI_RSTYPE_START_DPF; + + /* + * Point to Byte 1 if it is used + */ + if (2 == *bytes_consumed) { + buffer += 1; + temp8 = *buffer; + + /* + * Check Compatibility priority + */ + output_struct->data.start_dpf.compatibility_priority = temp8 & 0x03; + + if (3 == output_struct->data.start_dpf.compatibility_priority) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE); + } + + /* + * Check Performance/Robustness preference + */ + output_struct->data.start_dpf.performance_robustness = (temp8 >> 2) & 0x03; + + if (3 == output_struct->data.start_dpf.performance_robustness) { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE); + } + } + else { + output_struct->data.start_dpf.compatibility_priority = + ACPI_ACCEPTABLE_CONFIGURATION; + + output_struct->data.start_dpf.performance_robustness = + ACPI_ACCEPTABLE_CONFIGURATION; + } + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_end_depend_fns_resource + * + * PARAMETERS: byte_stream_buffer - Pointer to the resource input byte + * stream + * bytes_consumed - Pointer to where the number of bytes + * consumed the byte_stream_buffer is + * returned + * output_buffer - Pointer to the return data buffer + * structure_size - Pointer to where the number of bytes + * in the return data struct is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +acpi_status +acpi_rs_end_depend_fns_resource ( + u8 *byte_stream_buffer, + acpi_size *bytes_consumed, + u8 **output_buffer, + acpi_size *structure_size) +{ + struct acpi_resource *output_struct = (void *) *output_buffer; + acpi_size struct_size = ACPI_RESOURCE_LENGTH; + + + ACPI_FUNCTION_TRACE ("rs_end_depend_fns_resource"); + + + /* + * The number of bytes consumed is static + */ + *bytes_consumed = 1; + + /* + * Fill out the structure + */ + output_struct->id = ACPI_RSTYPE_END_DPF; + + /* + * Set the Length parameter + */ + output_struct->length = (u32) struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_start_depend_fns_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * output_buffer used + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_start_depend_fns_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 temp8 = 0; + + + ACPI_FUNCTION_TRACE ("rs_start_depend_fns_stream"); + + + /* + * The descriptor field is set based upon whether a byte is needed + * to contain Priority data. + */ + if (ACPI_ACCEPTABLE_CONFIGURATION == + linked_list->data.start_dpf.compatibility_priority && + ACPI_ACCEPTABLE_CONFIGURATION == + linked_list->data.start_dpf.performance_robustness) { + *buffer = 0x30; + } + else { + *buffer = 0x31; + buffer += 1; + + /* + * Set the Priority Byte Definition + */ + temp8 = 0; + temp8 = (u8) ((linked_list->data.start_dpf.performance_robustness & + 0x03) << 2); + temp8 |= (linked_list->data.start_dpf.compatibility_priority & + 0x03); + *buffer = temp8; + } + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_end_depend_fns_stream + * + * PARAMETERS: linked_list - Pointer to the resource linked list + * output_buffer - Pointer to the user's return buffer + * bytes_consumed - Pointer to where the number of bytes + * used in the output_buffer is returned + * + * RETURN: Status + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +acpi_status +acpi_rs_end_depend_fns_stream ( + struct acpi_resource *linked_list, + u8 **output_buffer, + acpi_size *bytes_consumed) +{ + u8 *buffer = *output_buffer; + + + ACPI_FUNCTION_TRACE ("rs_end_depend_fns_stream"); + + + /* + * The descriptor field is static + */ + *buffer = 0x38; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); + return_ACPI_STATUS (AE_OK); +} + diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c new file mode 100644 index 000000000000..ee9ce13c053d --- /dev/null +++ b/drivers/acpi/resources/rsutils.c @@ -0,0 +1,356 @@ +/******************************************************************************* + * + * Module Name: rsutils - Utilities for the resource manager + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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/acpi.h> +#include <acpi/acnamesp.h> +#include <acpi/acresrc.h> + + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsutils") + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_prt_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _PRT value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_prt_method_data ( + acpi_handle handle, + struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("rs_get_prt_method_data"); + + + /* Parameters guaranteed valid by caller */ + + /* + * Execute the method, no parameters + */ + status = acpi_ut_evaluate_object (handle, "_PRT", ACPI_BTYPE_PACKAGE, &obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Create a resource linked list from the byte stream buffer that comes + * back from the _CRS method execution. + */ + status = acpi_rs_create_pci_routing_table (obj_desc, ret_buffer); + + /* On exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference (obj_desc); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_crs_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _CRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_crs_method_data ( + acpi_handle handle, + struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("rs_get_crs_method_data"); + + + /* Parameters guaranteed valid by caller */ + + /* + * Execute the method, no parameters + */ + status = acpi_ut_evaluate_object (handle, "_CRS", ACPI_BTYPE_BUFFER, &obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list (obj_desc, ret_buffer); + + /* on exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference (obj_desc); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_prs_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _PRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE +acpi_status +acpi_rs_get_prs_method_data ( + acpi_handle handle, + struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("rs_get_prs_method_data"); + + + /* Parameters guaranteed valid by caller */ + + /* + * Execute the method, no parameters + */ + status = acpi_ut_evaluate_object (handle, "_PRS", ACPI_BTYPE_BUFFER, &obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list (obj_desc, ret_buffer); + + /* on exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference (obj_desc); + return_ACPI_STATUS (status); +} +#endif /* ACPI_FUTURE_USAGE */ + + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the _CRS or _PRS value of an + * object contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_get_method_data ( + acpi_handle handle, + char *path, + struct acpi_buffer *ret_buffer) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + + ACPI_FUNCTION_TRACE ("rs_get_method_data"); + + + /* Parameters guaranteed valid by caller */ + + /* + * Execute the method, no parameters + */ + status = acpi_ut_evaluate_object (handle, path, ACPI_BTYPE_BUFFER, &obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the method + * execution. + */ + status = acpi_rs_create_resource_list (obj_desc, ret_buffer); + + /* On exit, we must delete the object returned by evaluate_object */ + + acpi_ut_remove_reference (obj_desc); + return_ACPI_STATUS (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_srs_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * in_buffer - a pointer to a buffer structure of the + * parameter + * + * RETURN: Status + * + * DESCRIPTION: This function is called to set the _SRS of an object contained + * in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +acpi_status +acpi_rs_set_srs_method_data ( + acpi_handle handle, + struct acpi_buffer *in_buffer) +{ + struct acpi_parameter_info info; + union acpi_operand_object *params[2]; + acpi_status status; + struct acpi_buffer buffer; + + + ACPI_FUNCTION_TRACE ("rs_set_srs_method_data"); + + + /* Parameters guaranteed valid by caller */ + + /* + * The in_buffer parameter will point to a linked list of + * resource parameters. It needs to be formatted into a + * byte stream to be sent in as an input parameter to _SRS + * + * Convert the linked list into a byte stream + */ + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_create_byte_stream (in_buffer->pointer, &buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Init the param object + */ + params[0] = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!params[0]) { + acpi_os_free (buffer.pointer); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Set up the parameter object + */ + params[0]->buffer.length = (u32) buffer.length; + params[0]->buffer.pointer = buffer.pointer; + params[0]->common.flags = AOPOBJ_DATA_VALID; + params[1] = NULL; + + info.node = handle; + info.parameters = params; + info.parameter_type = ACPI_PARAM_ARGS; + + /* + * Execute the method, no return value + */ + status = acpi_ns_evaluate_relative ("_SRS", &info); + if (ACPI_SUCCESS (status)) { + /* Delete any return object (especially if implicit_return is enabled) */ + + if (info.return_object) { + acpi_ut_remove_reference (info.return_object); + } + } + + /* + * Clean up and return the status from acpi_ns_evaluate_relative + */ + acpi_ut_remove_reference (params[0]); + return_ACPI_STATUS (status); +} + diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c new file mode 100644 index 000000000000..a9cdcbeb3432 --- /dev/null +++ b/drivers/acpi/resources/rsxface.c @@ -0,0 +1,437 @@ +/******************************************************************************* + * + * Module Name: rsxface - Public interfaces to the resource manager + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2005, R. Byron Moore + * All rights reserved. + * + * 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 <linux/module.h> + +#include <acpi/acpi.h> +#include <acpi/acresrc.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsxface") + + +/******************************************************************************* + * + * FUNCTION: acpi_get_irq_routing_table + * + * PARAMETERS: device_handle - a handle to the Bus device we are querying + * ret_buffer - a pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the IRQ routing table for a + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed + * to by the ret_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. + * + * This function attempts to execute the _PRT method contained in + * the object indicated by the passed device_handle. + * + ******************************************************************************/ + +acpi_status +acpi_get_irq_routing_table ( + acpi_handle device_handle, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("acpi_get_irq_routing_table "); + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. + */ + if (!device_handle) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + status = acpi_ut_validate_buffer (ret_buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_rs_get_prt_method_data (device_handle, ret_buffer); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_get_current_resources + * + * PARAMETERS: device_handle - a handle to the device object for the + * device we are querying + * ret_buffer - a pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer + * pointed to by the ret_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. + * + * This function attempts to execute the _CRS method contained in + * the object indicated by the passed device_handle. + * + ******************************************************************************/ + +acpi_status +acpi_get_current_resources ( + acpi_handle device_handle, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("acpi_get_current_resources"); + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. + */ + if (!device_handle) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + status = acpi_ut_validate_buffer (ret_buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_rs_get_crs_method_data (device_handle, ret_buffer); + return_ACPI_STATUS (status); +} +EXPORT_SYMBOL(acpi_get_current_resources); + + +/******************************************************************************* + * + * FUNCTION: acpi_get_possible_resources + * + * PARAMETERS: device_handle - a handle to the device object for the + * device we are querying + * ret_buffer - a pointer to a buffer to receive the + * resources for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get a list of the possible resources + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the + * buffer pointed to by the ret_buffer variable. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. + * + ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE +acpi_status +acpi_get_possible_resources ( + acpi_handle device_handle, + struct acpi_buffer *ret_buffer) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("acpi_get_possible_resources"); + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. + */ + if (!device_handle) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + status = acpi_ut_validate_buffer (ret_buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_rs_get_prs_method_data (device_handle, ret_buffer); + return_ACPI_STATUS (status); +} +EXPORT_SYMBOL(acpi_get_possible_resources); +#endif /* ACPI_FUTURE_USAGE */ + + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - a handle to the device object for the + * device we are querying + * Path - method name of the resources we want + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * user_function - called for each resource + * Context - passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ + +acpi_status +acpi_walk_resources ( + acpi_handle device_handle, + char *path, + ACPI_WALK_RESOURCE_CALLBACK user_function, + void *context) +{ + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_resource *resource; + struct acpi_resource *buffer_end; + + + ACPI_FUNCTION_TRACE ("acpi_walk_resources"); + + + if (!device_handle || + (ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) && + ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + status = acpi_rs_get_method_data (device_handle, path, &buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Setup pointers */ + + resource = (struct acpi_resource *) buffer.pointer; + buffer_end = ACPI_CAST_PTR (struct acpi_resource, + ((u8 *) buffer.pointer + buffer.length)); + + /* Walk the resource list */ + + for (;;) { + if (!resource || resource->id == ACPI_RSTYPE_END_TAG) { + break; + } + + status = user_function (resource, context); + + switch (status) { + case AE_OK: + case AE_CTRL_DEPTH: + + /* Just keep going */ + + status = AE_OK; + break; + + case AE_CTRL_TERMINATE: + + /* Exit now, with OK stats */ + + status = AE_OK; + goto cleanup; + + default: + + /* All others are valid exceptions */ + + goto cleanup; + } + + /* Get the next resource descriptor */ + + resource = ACPI_NEXT_RESOURCE (resource); + + /* Check for end-of-buffer */ + + if (resource >= buffer_end) { + goto cleanup; + } + } + +cleanup: + + acpi_os_free (buffer.pointer); + return_ACPI_STATUS (status); +} +EXPORT_SYMBOL(acpi_walk_resources); + + +/******************************************************************************* + * + * FUNCTION: acpi_set_current_resources + * + * PARAMETERS: device_handle - a handle to the device object for the + * device we are changing the resources of + * in_buffer - a pointer to a buffer containing the + * resources to be set for the device + * + * RETURN: Status + * + * DESCRIPTION: This function is called to set the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine + * the buffer pointed to by the in_buffer variable. + * + ******************************************************************************/ + +acpi_status +acpi_set_current_resources ( + acpi_handle device_handle, + struct acpi_buffer *in_buffer) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("acpi_set_current_resources"); + + + /* + * Must have a valid handle and buffer + */ + if ((!device_handle) || + (!in_buffer) || + (!in_buffer->pointer) || + (!in_buffer->length)) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + status = acpi_rs_set_srs_method_data (device_handle, in_buffer); + return_ACPI_STATUS (status); +} +EXPORT_SYMBOL(acpi_set_current_resources); + + +#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field) +#define ACPI_COPY_ADDRESS(out, in) \ + ACPI_COPY_FIELD(out, in, resource_type); \ + ACPI_COPY_FIELD(out, in, producer_consumer); \ + ACPI_COPY_FIELD(out, in, decode); \ + ACPI_COPY_FIELD(out, in, min_address_fixed); \ + ACPI_COPY_FIELD(out, in, max_address_fixed); \ + ACPI_COPY_FIELD(out, in, attribute); \ + ACPI_COPY_FIELD(out, in, granularity); \ + ACPI_COPY_FIELD(out, in, min_address_range); \ + ACPI_COPY_FIELD(out, in, max_address_range); \ + ACPI_COPY_FIELD(out, in, address_translation_offset); \ + ACPI_COPY_FIELD(out, in, address_length); \ + ACPI_COPY_FIELD(out, in, resource_source); + +/****************************************************************************** + * + * FUNCTION: acpi_resource_to_address64 + * + * PARAMETERS: resource - Pointer to a resource + * out - Pointer to the users's return + * buffer (a struct + * struct acpi_resource_address64) + * + * RETURN: Status + * + * DESCRIPTION: If the resource is an address16, address32, or address64, + * copy it to the address64 return buffer. This saves the + * caller from having to duplicate code for different-sized + * addresses. + * + ******************************************************************************/ + +acpi_status +acpi_resource_to_address64 ( + struct acpi_resource *resource, + struct acpi_resource_address64 *out) +{ + struct acpi_resource_address16 *address16; + struct acpi_resource_address32 *address32; + + + switch (resource->id) { + case ACPI_RSTYPE_ADDRESS16: + + address16 = (struct acpi_resource_address16 *) &resource->data; + ACPI_COPY_ADDRESS(out, address16); + break; + + + case ACPI_RSTYPE_ADDRESS32: + + address32 = (struct acpi_resource_address32 *) &resource->data; + ACPI_COPY_ADDRESS(out, address32); + break; + + + case ACPI_RSTYPE_ADDRESS64: + + /* Simple copy for 64 bit source */ + + ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64)); + break; + + + default: + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} +EXPORT_SYMBOL(acpi_resource_to_address64); + |