162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: rsxface - Public interfaces to the resource manager 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci ******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define EXPORT_ACPI_INTERFACES 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acresrc.h" 1362306a36Sopenharmony_ci#include "acnamesp.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define _COMPONENT ACPI_RESOURCES 1662306a36Sopenharmony_ciACPI_MODULE_NAME("rsxface") 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Local macros for 16,32-bit to 64-bit conversion */ 1962306a36Sopenharmony_ci#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field) 2062306a36Sopenharmony_ci#define ACPI_COPY_ADDRESS(out, in) \ 2162306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, resource_type); \ 2262306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, producer_consumer); \ 2362306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, decode); \ 2462306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, min_address_fixed); \ 2562306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, max_address_fixed); \ 2662306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, info); \ 2762306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, address.granularity); \ 2862306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, address.minimum); \ 2962306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, address.maximum); \ 3062306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, address.translation_offset); \ 3162306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, address.address_length); \ 3262306a36Sopenharmony_ci ACPI_COPY_FIELD(out, in, resource_source); 3362306a36Sopenharmony_ci/* Local prototypes */ 3462306a36Sopenharmony_cistatic acpi_status 3562306a36Sopenharmony_ciacpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic acpi_status 3862306a36Sopenharmony_ciacpi_rs_validate_parameters(acpi_handle device_handle, 3962306a36Sopenharmony_ci struct acpi_buffer *buffer, 4062306a36Sopenharmony_ci struct acpi_namespace_node **return_node); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/******************************************************************************* 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * FUNCTION: acpi_rs_validate_parameters 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to a device 4762306a36Sopenharmony_ci * buffer - Pointer to a data buffer 4862306a36Sopenharmony_ci * return_node - Pointer to where the device node is returned 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * RETURN: Status 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * DESCRIPTION: Common parameter validation for resource interfaces 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci ******************************************************************************/ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic acpi_status 5762306a36Sopenharmony_ciacpi_rs_validate_parameters(acpi_handle device_handle, 5862306a36Sopenharmony_ci struct acpi_buffer *buffer, 5962306a36Sopenharmony_ci struct acpi_namespace_node **return_node) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci acpi_status status; 6262306a36Sopenharmony_ci struct acpi_namespace_node *node; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(rs_validate_parameters); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* 6762306a36Sopenharmony_ci * Must have a valid handle to an ACPI device 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci if (!device_handle) { 7062306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci node = acpi_ns_validate_handle(device_handle); 7462306a36Sopenharmony_ci if (!node) { 7562306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (node->type != ACPI_TYPE_DEVICE) { 7962306a36Sopenharmony_ci return_ACPI_STATUS(AE_TYPE); 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * Validate the user buffer object 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * if there is a non-zero buffer length we also need a valid pointer in 8662306a36Sopenharmony_ci * the buffer. If it's a zero buffer length, we'll be returning the 8762306a36Sopenharmony_ci * needed buffer size (later), so keep going. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci status = acpi_ut_validate_buffer(buffer); 9062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 9162306a36Sopenharmony_ci return_ACPI_STATUS(status); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci *return_node = node; 9562306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/******************************************************************************* 9962306a36Sopenharmony_ci * 10062306a36Sopenharmony_ci * FUNCTION: acpi_get_irq_routing_table 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to the Bus device we are querying 10362306a36Sopenharmony_ci * ret_buffer - Pointer to a buffer to receive the 10462306a36Sopenharmony_ci * current resources for the device 10562306a36Sopenharmony_ci * 10662306a36Sopenharmony_ci * RETURN: Status 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * DESCRIPTION: This function is called to get the IRQ routing table for a 10962306a36Sopenharmony_ci * specific bus. The caller must first acquire a handle for the 11062306a36Sopenharmony_ci * desired bus. The routine table is placed in the buffer pointed 11162306a36Sopenharmony_ci * to by the ret_buffer variable parameter. 11262306a36Sopenharmony_ci * 11362306a36Sopenharmony_ci * If the function fails an appropriate status will be returned 11462306a36Sopenharmony_ci * and the value of ret_buffer is undefined. 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * This function attempts to execute the _PRT method contained in 11762306a36Sopenharmony_ci * the object indicated by the passed device_handle. 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci ******************************************************************************/ 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciacpi_status 12262306a36Sopenharmony_ciacpi_get_irq_routing_table(acpi_handle device_handle, 12362306a36Sopenharmony_ci struct acpi_buffer *ret_buffer) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci acpi_status status; 12662306a36Sopenharmony_ci struct acpi_namespace_node *node; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Validate parameters then dispatch to internal routine */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); 13362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 13462306a36Sopenharmony_ci return_ACPI_STATUS(status); 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci status = acpi_rs_get_prt_method_data(node, ret_buffer); 13862306a36Sopenharmony_ci return_ACPI_STATUS(status); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/******************************************************************************* 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * FUNCTION: acpi_get_current_resources 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to the device object for the 14862306a36Sopenharmony_ci * device we are querying 14962306a36Sopenharmony_ci * ret_buffer - Pointer to a buffer to receive the 15062306a36Sopenharmony_ci * current resources for the device 15162306a36Sopenharmony_ci * 15262306a36Sopenharmony_ci * RETURN: Status 15362306a36Sopenharmony_ci * 15462306a36Sopenharmony_ci * DESCRIPTION: This function is called to get the current resources for a 15562306a36Sopenharmony_ci * specific device. The caller must first acquire a handle for 15662306a36Sopenharmony_ci * the desired device. The resource data is placed in the buffer 15762306a36Sopenharmony_ci * pointed to by the ret_buffer variable parameter. 15862306a36Sopenharmony_ci * 15962306a36Sopenharmony_ci * If the function fails an appropriate status will be returned 16062306a36Sopenharmony_ci * and the value of ret_buffer is undefined. 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci * This function attempts to execute the _CRS method contained in 16362306a36Sopenharmony_ci * the object indicated by the passed device_handle. 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci ******************************************************************************/ 16662306a36Sopenharmony_ciacpi_status 16762306a36Sopenharmony_ciacpi_get_current_resources(acpi_handle device_handle, 16862306a36Sopenharmony_ci struct acpi_buffer *ret_buffer) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci acpi_status status; 17162306a36Sopenharmony_ci struct acpi_namespace_node *node; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_get_current_resources); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Validate parameters then dispatch to internal routine */ 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); 17862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 17962306a36Sopenharmony_ci return_ACPI_STATUS(status); 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci status = acpi_rs_get_crs_method_data(node, ret_buffer); 18362306a36Sopenharmony_ci return_ACPI_STATUS(status); 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_get_current_resources) 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/******************************************************************************* 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * FUNCTION: acpi_get_possible_resources 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to the device object for the 19362306a36Sopenharmony_ci * device we are querying 19462306a36Sopenharmony_ci * ret_buffer - Pointer to a buffer to receive the 19562306a36Sopenharmony_ci * resources for the device 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * RETURN: Status 19862306a36Sopenharmony_ci * 19962306a36Sopenharmony_ci * DESCRIPTION: This function is called to get a list of the possible resources 20062306a36Sopenharmony_ci * for a specific device. The caller must first acquire a handle 20162306a36Sopenharmony_ci * for the desired device. The resource data is placed in the 20262306a36Sopenharmony_ci * buffer pointed to by the ret_buffer variable. 20362306a36Sopenharmony_ci * 20462306a36Sopenharmony_ci * If the function fails an appropriate status will be returned 20562306a36Sopenharmony_ci * and the value of ret_buffer is undefined. 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci ******************************************************************************/ 20862306a36Sopenharmony_ciacpi_status 20962306a36Sopenharmony_ciacpi_get_possible_resources(acpi_handle device_handle, 21062306a36Sopenharmony_ci struct acpi_buffer *ret_buffer) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci acpi_status status; 21362306a36Sopenharmony_ci struct acpi_namespace_node *node; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_get_possible_resources); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Validate parameters then dispatch to internal routine */ 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); 22062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 22162306a36Sopenharmony_ci return_ACPI_STATUS(status); 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci status = acpi_rs_get_prs_method_data(node, ret_buffer); 22562306a36Sopenharmony_ci return_ACPI_STATUS(status); 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_get_possible_resources) 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/******************************************************************************* 23162306a36Sopenharmony_ci * 23262306a36Sopenharmony_ci * FUNCTION: acpi_set_current_resources 23362306a36Sopenharmony_ci * 23462306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to the device object for the 23562306a36Sopenharmony_ci * device we are setting resources 23662306a36Sopenharmony_ci * in_buffer - Pointer to a buffer containing the 23762306a36Sopenharmony_ci * resources to be set for the device 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * RETURN: Status 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * DESCRIPTION: This function is called to set the current resources for a 24262306a36Sopenharmony_ci * specific device. The caller must first acquire a handle for 24362306a36Sopenharmony_ci * the desired device. The resource data is passed to the routine 24462306a36Sopenharmony_ci * the buffer pointed to by the in_buffer variable. 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci ******************************************************************************/ 24762306a36Sopenharmony_ciacpi_status 24862306a36Sopenharmony_ciacpi_set_current_resources(acpi_handle device_handle, 24962306a36Sopenharmony_ci struct acpi_buffer *in_buffer) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci acpi_status status; 25262306a36Sopenharmony_ci struct acpi_namespace_node *node; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_set_current_resources); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Validate the buffer, don't allow zero length */ 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { 25962306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Validate parameters then dispatch to internal routine */ 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci status = acpi_rs_validate_parameters(device_handle, in_buffer, &node); 26562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 26662306a36Sopenharmony_ci return_ACPI_STATUS(status); 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci status = acpi_rs_set_srs_method_data(node, in_buffer); 27062306a36Sopenharmony_ci return_ACPI_STATUS(status); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_set_current_resources) 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/******************************************************************************* 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * FUNCTION: acpi_get_event_resources 27862306a36Sopenharmony_ci * 27962306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to the device object for the 28062306a36Sopenharmony_ci * device we are getting resources 28162306a36Sopenharmony_ci * in_buffer - Pointer to a buffer containing the 28262306a36Sopenharmony_ci * resources to be set for the device 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * RETURN: Status 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * DESCRIPTION: This function is called to get the event resources for a 28762306a36Sopenharmony_ci * specific device. The caller must first acquire a handle for 28862306a36Sopenharmony_ci * the desired device. The resource data is passed to the routine 28962306a36Sopenharmony_ci * the buffer pointed to by the in_buffer variable. Uses the 29062306a36Sopenharmony_ci * _AEI method. 29162306a36Sopenharmony_ci * 29262306a36Sopenharmony_ci ******************************************************************************/ 29362306a36Sopenharmony_ciacpi_status 29462306a36Sopenharmony_ciacpi_get_event_resources(acpi_handle device_handle, 29562306a36Sopenharmony_ci struct acpi_buffer *ret_buffer) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci acpi_status status; 29862306a36Sopenharmony_ci struct acpi_namespace_node *node; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_get_event_resources); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* Validate parameters then dispatch to internal routine */ 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); 30562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 30662306a36Sopenharmony_ci return_ACPI_STATUS(status); 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci status = acpi_rs_get_aei_method_data(node, ret_buffer); 31062306a36Sopenharmony_ci return_ACPI_STATUS(status); 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_get_event_resources) 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci/****************************************************************************** 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * FUNCTION: acpi_resource_to_address64 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * PARAMETERS: resource - Pointer to a resource 32062306a36Sopenharmony_ci * out - Pointer to the users's return buffer 32162306a36Sopenharmony_ci * (a struct acpi_resource_address64) 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * RETURN: Status 32462306a36Sopenharmony_ci * 32562306a36Sopenharmony_ci * DESCRIPTION: If the resource is an address16, address32, or address64, 32662306a36Sopenharmony_ci * copy it to the address64 return buffer. This saves the 32762306a36Sopenharmony_ci * caller from having to duplicate code for different-sized 32862306a36Sopenharmony_ci * addresses. 32962306a36Sopenharmony_ci * 33062306a36Sopenharmony_ci ******************************************************************************/ 33162306a36Sopenharmony_ciacpi_status 33262306a36Sopenharmony_ciacpi_resource_to_address64(struct acpi_resource *resource, 33362306a36Sopenharmony_ci struct acpi_resource_address64 *out) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct acpi_resource_address16 *address16; 33662306a36Sopenharmony_ci struct acpi_resource_address32 *address32; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci if (!resource || !out) { 33962306a36Sopenharmony_ci return (AE_BAD_PARAMETER); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* Convert 16 or 32 address descriptor to 64 */ 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci switch (resource->type) { 34562306a36Sopenharmony_ci case ACPI_RESOURCE_TYPE_ADDRESS16: 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci address16 = 34862306a36Sopenharmony_ci ACPI_CAST_PTR(struct acpi_resource_address16, 34962306a36Sopenharmony_ci &resource->data); 35062306a36Sopenharmony_ci ACPI_COPY_ADDRESS(out, address16); 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci case ACPI_RESOURCE_TYPE_ADDRESS32: 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci address32 = 35662306a36Sopenharmony_ci ACPI_CAST_PTR(struct acpi_resource_address32, 35762306a36Sopenharmony_ci &resource->data); 35862306a36Sopenharmony_ci ACPI_COPY_ADDRESS(out, address32); 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci case ACPI_RESOURCE_TYPE_ADDRESS64: 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* Simple copy for 64 bit source */ 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci memcpy(out, &resource->data, 36662306a36Sopenharmony_ci sizeof(struct acpi_resource_address64)); 36762306a36Sopenharmony_ci break; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci default: 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci return (AE_BAD_PARAMETER); 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci return (AE_OK); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_resource_to_address64) 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci/******************************************************************************* 38062306a36Sopenharmony_ci * 38162306a36Sopenharmony_ci * FUNCTION: acpi_get_vendor_resource 38262306a36Sopenharmony_ci * 38362306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle for the parent device object 38462306a36Sopenharmony_ci * name - Method name for the parent resource 38562306a36Sopenharmony_ci * (METHOD_NAME__CRS or METHOD_NAME__PRS) 38662306a36Sopenharmony_ci * uuid - Pointer to the UUID to be matched. 38762306a36Sopenharmony_ci * includes both subtype and 16-byte UUID 38862306a36Sopenharmony_ci * ret_buffer - Where the vendor resource is returned 38962306a36Sopenharmony_ci * 39062306a36Sopenharmony_ci * RETURN: Status 39162306a36Sopenharmony_ci * 39262306a36Sopenharmony_ci * DESCRIPTION: Walk a resource template for the specified device to find a 39362306a36Sopenharmony_ci * vendor-defined resource that matches the supplied UUID and 39462306a36Sopenharmony_ci * UUID subtype. Returns a struct acpi_resource of type Vendor. 39562306a36Sopenharmony_ci * 39662306a36Sopenharmony_ci ******************************************************************************/ 39762306a36Sopenharmony_ciacpi_status 39862306a36Sopenharmony_ciacpi_get_vendor_resource(acpi_handle device_handle, 39962306a36Sopenharmony_ci char *name, 40062306a36Sopenharmony_ci struct acpi_vendor_uuid *uuid, 40162306a36Sopenharmony_ci struct acpi_buffer *ret_buffer) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct acpi_vendor_walk_info info; 40462306a36Sopenharmony_ci acpi_status status; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* Other parameters are validated by acpi_walk_resources */ 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (!uuid || !ret_buffer) { 40962306a36Sopenharmony_ci return (AE_BAD_PARAMETER); 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci info.uuid = uuid; 41362306a36Sopenharmony_ci info.buffer = ret_buffer; 41462306a36Sopenharmony_ci info.status = AE_NOT_EXIST; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci /* Walk the _CRS or _PRS resource list for this device */ 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci status = 41962306a36Sopenharmony_ci acpi_walk_resources(device_handle, name, 42062306a36Sopenharmony_ci acpi_rs_match_vendor_resource, &info); 42162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 42262306a36Sopenharmony_ci return (status); 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci return (info.status); 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci/******************************************************************************* 43162306a36Sopenharmony_ci * 43262306a36Sopenharmony_ci * FUNCTION: acpi_rs_match_vendor_resource 43362306a36Sopenharmony_ci * 43462306a36Sopenharmony_ci * PARAMETERS: acpi_walk_resource_callback 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * RETURN: Status 43762306a36Sopenharmony_ci * 43862306a36Sopenharmony_ci * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID 43962306a36Sopenharmony_ci * 44062306a36Sopenharmony_ci ******************************************************************************/ 44162306a36Sopenharmony_cistatic acpi_status 44262306a36Sopenharmony_ciacpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci struct acpi_vendor_walk_info *info = context; 44562306a36Sopenharmony_ci struct acpi_resource_vendor_typed *vendor; 44662306a36Sopenharmony_ci struct acpi_buffer *buffer; 44762306a36Sopenharmony_ci acpi_status status; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* Ignore all descriptors except Vendor */ 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { 45262306a36Sopenharmony_ci return (AE_OK); 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci vendor = &resource->data.vendor_typed; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* 45862306a36Sopenharmony_ci * For a valid match, these conditions must hold: 45962306a36Sopenharmony_ci * 46062306a36Sopenharmony_ci * 1) Length of descriptor data must be at least as long as a UUID struct 46162306a36Sopenharmony_ci * 2) The UUID subtypes must match 46262306a36Sopenharmony_ci * 3) The UUID data must match 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || 46562306a36Sopenharmony_ci (vendor->uuid_subtype != info->uuid->subtype) || 46662306a36Sopenharmony_ci (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { 46762306a36Sopenharmony_ci return (AE_OK); 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* Validate/Allocate/Clear caller buffer */ 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci buffer = info->buffer; 47362306a36Sopenharmony_ci status = acpi_ut_initialize_buffer(buffer, resource->length); 47462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 47562306a36Sopenharmony_ci return (status); 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* Found the correct resource, copy and return it */ 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci memcpy(buffer->pointer, resource, resource->length); 48162306a36Sopenharmony_ci buffer->length = resource->length; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* Found the desired descriptor, terminate resource walk */ 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci info->status = AE_OK; 48662306a36Sopenharmony_ci return (AE_CTRL_TERMINATE); 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci/******************************************************************************* 49062306a36Sopenharmony_ci * 49162306a36Sopenharmony_ci * FUNCTION: acpi_walk_resource_buffer 49262306a36Sopenharmony_ci * 49362306a36Sopenharmony_ci * PARAMETERS: buffer - Formatted buffer returned by one of the 49462306a36Sopenharmony_ci * various Get*Resource functions 49562306a36Sopenharmony_ci * user_function - Called for each resource 49662306a36Sopenharmony_ci * context - Passed to user_function 49762306a36Sopenharmony_ci * 49862306a36Sopenharmony_ci * RETURN: Status 49962306a36Sopenharmony_ci * 50062306a36Sopenharmony_ci * DESCRIPTION: Walks the input resource template. The user_function is called 50162306a36Sopenharmony_ci * once for each resource in the list. 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci ******************************************************************************/ 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ciacpi_status 50662306a36Sopenharmony_ciacpi_walk_resource_buffer(struct acpi_buffer *buffer, 50762306a36Sopenharmony_ci acpi_walk_resource_callback user_function, 50862306a36Sopenharmony_ci void *context) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci acpi_status status = AE_OK; 51162306a36Sopenharmony_ci struct acpi_resource *resource; 51262306a36Sopenharmony_ci struct acpi_resource *resource_end; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci /* Parameter validation */ 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (!buffer || !buffer->pointer || !user_function) { 51962306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* Buffer contains the resource list and length */ 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer); 52562306a36Sopenharmony_ci resource_end = 52662306a36Sopenharmony_ci ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci /* Walk the resource list until the end_tag is found (or buffer end) */ 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci while (resource < resource_end) { 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci /* Sanity check the resource type */ 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (resource->type > ACPI_RESOURCE_TYPE_MAX) { 53562306a36Sopenharmony_ci status = AE_AML_INVALID_RESOURCE_TYPE; 53662306a36Sopenharmony_ci break; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* Sanity check the length. It must not be zero, or we loop forever */ 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (!resource->length) { 54262306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci /* Invoke the user function, abort on any error returned */ 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci status = user_function(resource, context); 54862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 54962306a36Sopenharmony_ci if (status == AE_CTRL_TERMINATE) { 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci /* This is an OK termination by the user function */ 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci status = AE_OK; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* end_tag indicates end-of-list */ 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { 56162306a36Sopenharmony_ci break; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci /* Get the next resource descriptor */ 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci resource = ACPI_NEXT_RESOURCE(resource); 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return_ACPI_STATUS(status); 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer) 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci/******************************************************************************* 57562306a36Sopenharmony_ci * 57662306a36Sopenharmony_ci * FUNCTION: acpi_walk_resources 57762306a36Sopenharmony_ci * 57862306a36Sopenharmony_ci * PARAMETERS: device_handle - Handle to the device object for the 57962306a36Sopenharmony_ci * device we are querying 58062306a36Sopenharmony_ci * name - Method name of the resources we want. 58162306a36Sopenharmony_ci * (METHOD_NAME__CRS, METHOD_NAME__PRS, or 58262306a36Sopenharmony_ci * METHOD_NAME__AEI or METHOD_NAME__DMA) 58362306a36Sopenharmony_ci * user_function - Called for each resource 58462306a36Sopenharmony_ci * context - Passed to user_function 58562306a36Sopenharmony_ci * 58662306a36Sopenharmony_ci * RETURN: Status 58762306a36Sopenharmony_ci * 58862306a36Sopenharmony_ci * DESCRIPTION: Retrieves the current or possible resource list for the 58962306a36Sopenharmony_ci * specified device. The user_function is called once for 59062306a36Sopenharmony_ci * each resource in the list. 59162306a36Sopenharmony_ci * 59262306a36Sopenharmony_ci ******************************************************************************/ 59362306a36Sopenharmony_ciacpi_status 59462306a36Sopenharmony_ciacpi_walk_resources(acpi_handle device_handle, 59562306a36Sopenharmony_ci char *name, 59662306a36Sopenharmony_ci acpi_walk_resource_callback user_function, void *context) 59762306a36Sopenharmony_ci{ 59862306a36Sopenharmony_ci acpi_status status; 59962306a36Sopenharmony_ci struct acpi_buffer buffer; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_walk_resources); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* Parameter validation */ 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci if (!device_handle || !user_function || !name || 60662306a36Sopenharmony_ci (!ACPI_COMPARE_NAMESEG(name, METHOD_NAME__CRS) && 60762306a36Sopenharmony_ci !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__PRS) && 60862306a36Sopenharmony_ci !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__AEI) && 60962306a36Sopenharmony_ci !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__DMA))) { 61062306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* Get the _CRS/_PRS/_AEI/_DMA resource list */ 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 61662306a36Sopenharmony_ci status = acpi_rs_get_method_data(device_handle, name, &buffer); 61762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 61862306a36Sopenharmony_ci return_ACPI_STATUS(status); 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* Walk the resource list and cleanup */ 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci status = acpi_walk_resource_buffer(&buffer, user_function, context); 62462306a36Sopenharmony_ci ACPI_FREE(buffer.pointer); 62562306a36Sopenharmony_ci return_ACPI_STATUS(status); 62662306a36Sopenharmony_ci} 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_walk_resources) 629