diff options
author | jkim <jkim@FreeBSD.org> | 2012-02-16 22:59:29 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2012-02-16 22:59:29 +0000 |
commit | a561c762bacb78b14d2bf5fb20afc1566203f990 (patch) | |
tree | d4ae2db1980d2ec7b164b1a5658fd2ae62569456 /sys/contrib/dev/acpica/components/resources/rscreate.c | |
parent | 2b86faa18cb89921d202e133fa6a1c39b63cfe16 (diff) | |
parent | a6dfe3119152f97e640cc135d963b9f7c95c84ef (diff) | |
download | FreeBSD-src-a561c762bacb78b14d2bf5fb20afc1566203f990.zip FreeBSD-src-a561c762bacb78b14d2bf5fb20afc1566203f990.tar.gz |
Merge ACPICA 20120215.
Diffstat (limited to 'sys/contrib/dev/acpica/components/resources/rscreate.c')
-rw-r--r-- | sys/contrib/dev/acpica/components/resources/rscreate.c | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c new file mode 100644 index 0000000..dd1f6ae --- /dev/null +++ b/sys/contrib/dev/acpica/components/resources/rscreate.c @@ -0,0 +1,534 @@ +/******************************************************************************* + * + * Module Name: rscreate - Create resource lists/tables + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * 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. + */ + +#define __RSCREATE_C__ + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/acresrc.h> +#include <contrib/dev/acpica/include/acnamesp.h> + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rscreate") + + +/******************************************************************************* + * + * FUNCTION: AcpiBufferToResource + * + * PARAMETERS: AmlBuffer - Pointer to the resource byte stream + * AmlBufferLength - Length of the AmlBuffer + * ResourcePtr - Where the converted resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a raw AML buffer to a resource list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiBufferToResource ( + UINT8 *AmlBuffer, + UINT16 AmlBufferLength, + ACPI_RESOURCE **ResourcePtr) +{ + ACPI_STATUS Status; + ACPI_SIZE ListSizeNeeded; + void *Resource; + void *CurrentResourcePtr; + + /* + * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag + * is not required here. + */ + + /* Get the required length for the converted resource */ + + Status = AcpiRsGetListLength (AmlBuffer, AmlBufferLength, + &ListSizeNeeded); + if (Status == AE_AML_NO_RESOURCE_END_TAG) + { + Status = AE_OK; + } + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Allocate a buffer for the converted resource */ + + Resource = ACPI_ALLOCATE_ZEROED (ListSizeNeeded); + CurrentResourcePtr = Resource; + if (!Resource) + { + return (AE_NO_MEMORY); + } + + /* Perform the AML-to-Resource conversion */ + + Status = AcpiUtWalkAmlResources (AmlBuffer, AmlBufferLength, + AcpiRsConvertAmlToResources, &CurrentResourcePtr); + if (Status == AE_AML_NO_RESOURCE_END_TAG) + { + Status = AE_OK; + } + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (Resource); + } + else + { + *ResourcePtr = Resource; + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCreateResourceList + * + * PARAMETERS: AmlBuffer - Pointer to the resource byte stream + * OutputBuffer - Pointer to the user's buffer + * + * RETURN: Status: AE_OK if okay, else a valid ACPI_STATUS code + * If OutputBuffer is not large enough, OutputBufferLength + * indicates how large OutputBuffer should be, else it + * indicates how may UINT8 elements of OutputBuffer 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 +AcpiRsCreateResourceList ( + ACPI_OPERAND_OBJECT *AmlBuffer, + ACPI_BUFFER *OutputBuffer) +{ + + ACPI_STATUS Status; + UINT8 *AmlStart; + ACPI_SIZE ListSizeNeeded = 0; + UINT32 AmlBufferLength; + void *Resource; + + + ACPI_FUNCTION_TRACE (RsCreateResourceList); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AmlBuffer = %p\n", + AmlBuffer)); + + /* Params already validated, so we don't re-validate here */ + + AmlBufferLength = AmlBuffer->Buffer.Length; + AmlStart = AmlBuffer->Buffer.Pointer; + + /* + * Pass the AmlBuffer into a module that can calculate + * the buffer size needed for the linked list + */ + Status = AcpiRsGetListLength (AmlStart, AmlBufferLength, + &ListSizeNeeded); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n", + Status, (UINT32) ListSizeNeeded)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutputBuffer, ListSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Do the conversion */ + + Resource = OutputBuffer->Pointer; + Status = AcpiUtWalkAmlResources (AmlStart, AmlBufferLength, + AcpiRsConvertAmlToResources, &Resource); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + OutputBuffer->Pointer, (UINT32) OutputBuffer->Length)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCreatePciRoutingTable + * + * PARAMETERS: PackageObject - Pointer to an ACPI_OPERAND_OBJECT + * package + * OutputBuffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the OutputBuffer is too small, the error will be + * AE_BUFFER_OVERFLOW and OutputBuffer->Length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the 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 +AcpiRsCreatePciRoutingTable ( + ACPI_OPERAND_OBJECT *PackageObject, + ACPI_BUFFER *OutputBuffer) +{ + UINT8 *Buffer; + ACPI_OPERAND_OBJECT **TopObjectList; + ACPI_OPERAND_OBJECT **SubObjectList; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_SIZE BufferSizeNeeded = 0; + UINT32 NumberOfElements; + UINT32 Index; + ACPI_PCI_ROUTING_TABLE *UserPrt; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + ACPI_BUFFER PathBuffer; + + + ACPI_FUNCTION_TRACE (RsCreatePciRoutingTable); + + + /* Params already validated, so we don't re-validate here */ + + /* Get the required buffer length */ + + Status = AcpiRsGetPciRoutingTableLength (PackageObject, + &BufferSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "BufferSizeNeeded = %X\n", + (UINT32) BufferSizeNeeded)); + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutputBuffer, BufferSizeNeeded); + 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 UINT64 Address, a UINT8 Pin, + * a Name, and a UINT8 SourceIndex. + */ + TopObjectList = PackageObject->Package.Elements; + NumberOfElements = PackageObject->Package.Count; + Buffer = OutputBuffer->Pointer; + UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer); + + for (Index = 0; Index < NumberOfElements; Index++) + { + /* + * Point UserPrt past this current structure + * + * NOTE: On the first iteration, UserPrt->Length will + * be zero because we cleared the return buffer earlier + */ + Buffer += UserPrt->Length; + UserPrt = ACPI_CAST_PTR (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 UINT8 Source[4] member + * because it is added below. + */ + UserPrt->Length = (sizeof (ACPI_PCI_ROUTING_TABLE) - 4); + + /* Each element of the top-level package must also be a package */ + + if ((*TopObjectList)->Common.Type != ACPI_TYPE_PACKAGE) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u]) Need sub-package, found %s", + Index, AcpiUtGetObjectTypeName (*TopObjectList))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Each sub-package must be of length 4 */ + + if ((*TopObjectList)->Package.Count != 4) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u]) Need package of length 4, found length %u", + Index, (*TopObjectList)->Package.Count)); + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + + /* + * Dereference the sub-package. + * The SubObjectList will now point to an array of the four IRQ + * elements: [Address, Pin, Source, SourceIndex] + */ + SubObjectList = (*TopObjectList)->Package.Elements; + + /* 1) First subobject: Dereference the PRT.Address */ + + ObjDesc = SubObjectList[0]; + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, "(PRT[%u].Address) Need Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + UserPrt->Address = ObjDesc->Integer.Value; + + /* 2) Second subobject: Dereference the PRT.Pin */ + + ObjDesc = SubObjectList[1]; + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + UserPrt->Pin = (UINT32) ObjDesc->Integer.Value; + + /* + * If the BIOS has erroneously reversed the _PRT SourceName (index 2) + * and the SourceIndex (index 3), fix it. _PRT is important enough to + * workaround this BIOS error. This also provides compatibility with + * other ACPI implementations. + */ + ObjDesc = SubObjectList[3]; + if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) + { + SubObjectList[3] = SubObjectList[2]; + SubObjectList[2] = ObjDesc; + + ACPI_WARNING ((AE_INFO, + "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", + Index)); + } + + /* + * 3) Third subobject: Dereference the PRT.SourceName + * The name may be unresolved (slack mode), so allow a null object + */ + ObjDesc = SubObjectList[2]; + if (ObjDesc) + { + switch (ObjDesc->Common.Type) + { + case ACPI_TYPE_LOCAL_REFERENCE: + + if (ObjDesc->Reference.Class != ACPI_REFCLASS_NAME) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u].Source) Need name, found Reference Class 0x%X", + Index, ObjDesc->Reference.Class)); + return_ACPI_STATUS (AE_BAD_DATA); + } + + Node = ObjDesc->Reference.Node; + + /* Use *remaining* length of the buffer as max for pathname */ + + PathBuffer.Length = OutputBuffer->Length - + (UINT32) ((UINT8 *) UserPrt->Source - + (UINT8 *) OutputBuffer->Pointer); + PathBuffer.Pointer = UserPrt->Source; + + Status = AcpiNsHandleToPathname ((ACPI_HANDLE) Node, &PathBuffer); + + /* +1 to include null terminator */ + + UserPrt->Length += (UINT32) ACPI_STRLEN (UserPrt->Source) + 1; + break; + + + case ACPI_TYPE_STRING: + + ACPI_STRCPY (UserPrt->Source, ObjDesc->String.Pointer); + + /* + * Add to the Length field the length of the string + * (add 1 for terminator) + */ + UserPrt->Length += ObjDesc->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 UINT32 NULL + */ + UserPrt->Length += sizeof (UINT32); + break; + + + default: + + ACPI_ERROR ((AE_INFO, + "(PRT[%u].Source) Need Ref/String/Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + } + + /* Now align the current length */ + + UserPrt->Length = (UINT32) ACPI_ROUND_UP_TO_64BIT (UserPrt->Length); + + /* 4) Fourth subobject: Dereference the PRT.SourceIndex */ + + ObjDesc = SubObjectList[3]; + if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, + "(PRT[%u].SourceIndex) Need Integer, found %s", + Index, AcpiUtGetObjectTypeName (ObjDesc))); + return_ACPI_STATUS (AE_BAD_DATA); + } + + UserPrt->SourceIndex = (UINT32) ObjDesc->Integer.Value; + + /* Point to the next ACPI_OPERAND_OBJECT in the top level package */ + + TopObjectList++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + OutputBuffer->Pointer, (UINT32) OutputBuffer->Length)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiRsCreateAmlResources + * + * PARAMETERS: LinkedListBuffer - Pointer to the resource linked list + * OutputBuffer - Pointer to the user's buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the OutputBuffer is too small, the error will be + * AE_BUFFER_OVERFLOW and OutputBuffer->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 +AcpiRsCreateAmlResources ( + ACPI_RESOURCE *LinkedListBuffer, + ACPI_BUFFER *OutputBuffer) +{ + ACPI_STATUS Status; + ACPI_SIZE AmlSizeNeeded = 0; + + + ACPI_FUNCTION_TRACE (RsCreateAmlResources); + + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "LinkedListBuffer = %p\n", + LinkedListBuffer)); + + /* + * Params already validated, so we don't re-validate here + * + * Pass the LinkedListBuffer into a module that calculates + * the buffer size needed for the byte stream. + */ + Status = AcpiRsGetAmlLength (LinkedListBuffer, + &AmlSizeNeeded); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", + (UINT32) AmlSizeNeeded, AcpiFormatException (Status))); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutputBuffer, AmlSizeNeeded); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Do the conversion */ + + Status = AcpiRsConvertResourcesToAml (LinkedListBuffer, AmlSizeNeeded, + OutputBuffer->Pointer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", + OutputBuffer->Pointer, (UINT32) OutputBuffer->Length)); + return_ACPI_STATUS (AE_OK); +} + |