2005-04-16 15:20:36 -07:00
/*******************************************************************************
*
* 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
2005-08-05 00:44:28 -04:00
ACPI_MODULE_NAME ( " rscalc " )
2005-04-16 15:20:36 -07:00
/*******************************************************************************
*
* 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
2005-08-05 00:44:28 -04:00
acpi_rs_get_byte_stream_length ( struct acpi_resource * linked_list ,
acpi_size * size_needed )
2005-04-16 15:20:36 -07:00
{
2005-08-05 00:44:28 -04:00
acpi_size byte_stream_size_needed = 0 ;
acpi_size segment_size ;
u8 done = FALSE ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
ACPI_FUNCTION_TRACE ( " rs_get_byte_stream_length " ) ;
2005-04-16 15:20:36 -07:00
while ( ! done ) {
2005-04-18 22:49:35 -04:00
/* Init the variable that will hold the size to add to the total. */
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
segment_size = 1 ;
}
2005-08-05 00:44:28 -04:00
segment_size + =
linked_list - > data . vendor_specific . length ;
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
if ( linked_list - > data . address16 . resource_source .
string_ptr ) {
2005-04-18 22:49:35 -04:00
segment_size + =
2005-08-05 00:44:28 -04:00
linked_list - > data . address16 . resource_source .
string_length ;
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
if ( linked_list - > data . address32 . resource_source .
string_ptr ) {
2005-04-18 22:49:35 -04:00
segment_size + =
2005-08-05 00:44:28 -04:00
linked_list - > data . address32 . resource_source .
string_length ;
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
if ( linked_list - > data . address64 . resource_source .
string_ptr ) {
2005-04-18 22:49:35 -04:00
segment_size + =
2005-08-05 00:44:28 -04:00
linked_list - > data . address64 . resource_source .
string_length ;
2005-04-16 15:20:36 -07:00
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 .
*/
2005-04-18 22:49:35 -04:00
segment_size = 9 + ( ( ( acpi_size )
2005-08-05 00:44:28 -04:00
linked_list - > data . extended_irq .
number_of_interrupts - 1 ) * 4 ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
if ( linked_list - > data . extended_irq . resource_source .
string_ptr ) {
2005-04-18 22:49:35 -04:00
segment_size + =
2005-08-05 00:44:28 -04:00
linked_list - > data . extended_irq .
resource_source . string_length ;
2005-04-16 15:20:36 -07:00
segment_size + + ;
}
break ;
default :
2005-04-18 22:49:35 -04:00
/* If we get here, everything is out of sync, exit with error */
2005-08-05 00:44:28 -04:00
return_ACPI_STATUS ( AE_AML_INVALID_RESOURCE_TYPE ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
} /* switch (linked_list->Id) */
2005-04-16 15:20:36 -07:00
2005-04-18 22:49:35 -04:00
/* Update the total */
2005-04-16 15:20:36 -07:00
byte_stream_size_needed + = segment_size ;
2005-04-18 22:49:35 -04:00
/* Point to the next object */
2005-08-05 00:44:28 -04:00
linked_list = ACPI_PTR_ADD ( struct acpi_resource ,
linked_list , linked_list - > length ) ;
2005-04-16 15:20:36 -07:00
}
2005-04-18 22:49:35 -04:00
/* This is the data the caller needs */
2005-04-16 15:20:36 -07:00
* size_needed = byte_stream_size_needed ;
2005-08-05 00:44:28 -04:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-16 15:20:36 -07:00
}
/*******************************************************************************
*
* 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
2005-08-05 00:44:28 -04:00
acpi_rs_get_list_length ( u8 * byte_stream_buffer ,
u32 byte_stream_buffer_length , acpi_size * size_needed )
2005-04-16 15:20:36 -07:00
{
2005-08-05 00:44:28 -04:00
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 " ) ;
2005-04-16 15:20:36 -07:00
while ( bytes_parsed < byte_stream_buffer_length ) {
2005-04-18 22:49:35 -04:00
/* The next byte in the stream is the resource type */
2005-08-05 00:44:28 -04:00
resource_type = acpi_rs_get_resource_type ( * byte_stream_buffer ) ;
2005-04-16 15:20:36 -07:00
switch ( resource_type ) {
case ACPI_RDESC_TYPE_MEMORY_24 :
/*
* 24 - Bit Memory Resource
*/
bytes_consumed = 12 ;
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_mem24 ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_LARGE_VENDOR :
/*
* Vendor Defined Resource
*/
buffer = byte_stream_buffer ;
+ + buffer ;
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
bytes_consumed = temp16 + 3 ;
2005-04-18 22:49:35 -04:00
/* Ensure a 32-bit boundary for the structure */
2005-08-05 00:44:28 -04:00
temp16 = ( u16 ) ACPI_ROUND_UP_to_32_bITS ( temp16 ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_vendor ) +
( temp16 * sizeof ( u8 ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_MEMORY_32 :
/*
* 32 - Bit Memory Range Resource
*/
bytes_consumed = 20 ;
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_mem32 ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_FIXED_MEMORY_32 :
/*
* 32 - Bit Fixed Memory Resource
*/
bytes_consumed = 12 ;
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct
acpi_resource_fixed_mem32 ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE :
/*
* 64 - Bit Address Resource
*/
buffer = byte_stream_buffer ;
+ + buffer ;
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
bytes_consumed = temp16 + 3 ;
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct
acpi_resource_address64 ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE :
/*
* 64 - Bit Address Resource
*/
buffer = byte_stream_buffer ;
+ + buffer ;
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
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 ) ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
temp8 = 0 ;
}
2005-04-18 22:49:35 -04:00
/* Ensure a 64-bit boundary for the structure */
2005-08-05 00:44:28 -04:00
temp8 = ( u8 ) ACPI_ROUND_UP_to_64_bITS ( temp8 ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_address64 )
+ ( temp8 * sizeof ( u8 ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE :
/*
* 32 - Bit Address Resource
*/
buffer = byte_stream_buffer ;
+ + buffer ;
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
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 ) ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
temp8 = 0 ;
}
2005-04-18 22:49:35 -04:00
/* Ensure a 32-bit boundary for the structure */
2005-08-05 00:44:28 -04:00
temp8 = ( u8 ) ACPI_ROUND_UP_to_32_bITS ( temp8 ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_address32 )
+ ( temp8 * sizeof ( u8 ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE :
/*
* 16 - Bit Address Resource
*/
buffer = byte_stream_buffer ;
+ + buffer ;
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
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 ) ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
temp8 = 0 ;
}
2005-04-18 22:49:35 -04:00
/* Ensure a 32-bit boundary for the structure */
2005-08-05 00:44:28 -04:00
temp8 = ( u8 ) ACPI_ROUND_UP_to_32_bITS ( temp8 ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_address16 )
+ ( temp8 * sizeof ( u8 ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_EXTENDED_XRUPT :
/*
* Extended IRQ
*/
buffer = byte_stream_buffer ;
+ + buffer ;
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
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 ) ) ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
temp8 = 0 ;
}
2005-04-18 22:49:35 -04:00
/* Ensure a 32-bit boundary for the structure */
2005-08-05 00:44:28 -04:00
temp8 = ( u8 ) ACPI_ROUND_UP_to_32_bITS ( temp8 ) ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_ext_irq ) +
( additional_bytes * sizeof ( u8 ) ) +
( temp8 * sizeof ( u8 ) ) ;
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
if ( temp8 & 0x01 ) {
2005-04-16 15:20:36 -07:00
bytes_consumed = 4 ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
bytes_consumed = 3 ;
}
/* Point past the descriptor */
+ + buffer ;
2005-04-18 22:49:35 -04:00
/* Look at the number of bits set */
2005-08-05 00:44:28 -04:00
ACPI_MOVE_16_TO_16 ( & temp16 , buffer ) ;
2005-04-16 15:20:36 -07:00
for ( index = 0 ; index < 16 ; index + + ) {
if ( temp16 & 0x1 ) {
+ + number_of_interrupts ;
}
temp16 > > = 1 ;
}
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_io ) +
( number_of_interrupts * sizeof ( u32 ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_DMA_FORMAT :
/*
* DMA Resource
*/
buffer = byte_stream_buffer ;
bytes_consumed = 3 ;
/* Point past the descriptor */
+ + buffer ;
2005-04-18 22:49:35 -04:00
/* Look at the number of bits set */
2005-04-16 15:20:36 -07:00
temp8 = * buffer ;
2005-08-05 00:44:28 -04:00
for ( index = 0 ; index < 8 ; index + + ) {
if ( temp8 & 0x1 ) {
2005-04-16 15:20:36 -07:00
+ + number_of_channels ;
}
temp8 > > = 1 ;
}
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_dma ) +
( number_of_channels * sizeof ( u32 ) ) ;
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
if ( temp8 & 0x01 ) {
2005-04-16 15:20:36 -07:00
bytes_consumed = 2 ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
bytes_consumed = 1 ;
}
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct
acpi_resource_start_dpf ) ;
2005-04-16 15:20:36 -07:00
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 ;
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_io ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_FIXED_IO_PORT :
/*
* Fixed IO Port Resource
*/
bytes_consumed = 4 ;
2005-08-05 00:44:28 -04:00
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_fixed_io ) ;
2005-04-16 15:20:36 -07:00
break ;
case ACPI_RDESC_TYPE_SMALL_VENDOR :
/*
* Vendor Specific Resource
*/
buffer = byte_stream_buffer ;
temp8 = * buffer ;
temp8 = ( u8 ) ( temp8 & 0x7 ) ;
bytes_consumed = temp8 + 1 ;
2005-04-18 22:49:35 -04:00
/* Ensure a 32-bit boundary for the structure */
2005-08-05 00:44:28 -04:00
temp8 = ( u8 ) ACPI_ROUND_UP_to_32_bITS ( temp8 ) ;
structure_size =
ACPI_SIZEOF_RESOURCE ( struct acpi_resource_vendor ) +
( temp8 * sizeof ( u8 ) ) ;
2005-04-16 15:20:36 -07:00
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
*/
2005-08-05 00:44:28 -04:00
return_ACPI_STATUS ( AE_AML_INVALID_RESOURCE_TYPE ) ;
2005-04-16 15:20:36 -07:00
}
2005-04-18 22:49:35 -04:00
/* Update the return value and counter */
2005-08-05 00:44:28 -04:00
buffer_size + = ( u32 ) ACPI_ALIGN_RESOURCE_SIZE ( structure_size ) ;
2005-04-16 15:20:36 -07:00
bytes_parsed + = bytes_consumed ;
2005-04-18 22:49:35 -04:00
/* Set the byte stream to point to the next resource */
2005-04-16 15:20:36 -07:00
byte_stream_buffer + = bytes_consumed ;
}
2005-04-18 22:49:35 -04:00
/* This is the data the caller needs */
2005-04-16 15:20:36 -07:00
* size_needed = buffer_size ;
2005-08-05 00:44:28 -04:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-16 15:20:36 -07:00
}
/*******************************************************************************
*
* 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
2005-08-05 00:44:28 -04:00
acpi_rs_get_pci_routing_table_length ( union acpi_operand_object * package_object ,
acpi_size * buffer_size_needed )
2005-04-16 15:20:36 -07:00
{
2005-08-05 00:44:28 -04:00
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 ;
2005-04-16 15:20:36 -07:00
2005-08-05 00:44:28 -04:00
ACPI_FUNCTION_TRACE ( " rs_get_pci_routing_table_length " ) ;
2005-04-16 15:20:36 -07:00
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 + + ) {
2005-04-18 22:49:35 -04:00
/* Dereference the sub-package */
2005-04-16 15:20:36 -07:00
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 ;
2005-04-18 22:49:35 -04:00
/* Scan the irq_table_elements for the Source Name String */
2005-04-16 15:20:36 -07:00
name_found = FALSE ;
2005-08-05 00:44:28 -04:00
for ( table_index = 0 ; table_index < 4 & & ! name_found ;
table_index + + ) {
2005-04-18 22:49:35 -04:00
if ( ( ACPI_TYPE_STRING = =
2005-08-05 00:44:28 -04:00
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 ) ) ) {
2005-04-16 15:20:36 -07:00
name_found = TRUE ;
2005-08-05 00:44:28 -04:00
} else {
2005-04-18 22:49:35 -04:00
/* Look at the next element */
2005-04-16 15:20:36 -07:00
sub_object_list + + ;
}
}
2005-08-05 00:44:28 -04:00
temp_size_needed + = ( sizeof ( struct acpi_pci_routing_table ) - 4 ) ;
2005-04-16 15:20:36 -07:00
2005-04-18 22:49:35 -04:00
/* Was a String type found? */
2005-04-16 15:20:36 -07:00
if ( name_found ) {
2005-08-05 00:44:28 -04:00
if ( ACPI_GET_OBJECT_TYPE ( * sub_object_list ) = =
ACPI_TYPE_STRING ) {
2005-04-16 15:20:36 -07:00
/*
* The length String . Length field does not include the
* terminating NULL , add 1
*/
2005-04-18 22:49:35 -04:00
temp_size_needed + = ( ( acpi_size )
2005-08-05 00:44:28 -04:00
( * sub_object_list ) - > string .
length + 1 ) ;
} else {
temp_size_needed + = acpi_ns_get_pathname_length ( ( * sub_object_list ) - > reference . node ) ;
2005-04-16 15:20:36 -07:00
}
2005-08-05 00:44:28 -04:00
} else {
2005-04-16 15:20:36 -07:00
/*
* If no name was found , then this is a NULL , which is
* translated as a u32 zero .
*/
2005-08-05 00:44:28 -04:00
temp_size_needed + = sizeof ( u32 ) ;
2005-04-16 15:20:36 -07:00
}
/* Round up the size since each element must be aligned */
2005-08-05 00:44:28 -04:00
temp_size_needed = ACPI_ROUND_UP_to_64_bITS ( temp_size_needed ) ;
2005-04-16 15:20:36 -07:00
2005-04-18 22:49:35 -04:00
/* Point to the next union acpi_operand_object */
2005-04-16 15:20:36 -07:00
top_object_list + + ;
}
/*
2005-04-18 22:49:35 -04:00
* Adding an extra element to the end of the list , essentially a
* NULL terminator
2005-04-16 15:20:36 -07:00
*/
2005-08-05 00:44:28 -04:00
* buffer_size_needed =
temp_size_needed + sizeof ( struct acpi_pci_routing_table ) ;
return_ACPI_STATUS ( AE_OK ) ;
2005-04-16 15:20:36 -07:00
}