X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fresources%2Frsxface.c;h=1999e2ab7daad1971559302ae9e0e05b21c33e3e;hb=refs%2Fheads%2Fvserver;hp=d02aa1df32855a948b02b850dbeced6c64ae30de;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index d02aa1df3..1999e2ab7 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2004, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,27 +41,106 @@ * POSSIBILITY OF SUCH DAMAGES. */ - #include #include +#include #define _COMPONENT ACPI_RESOURCES - ACPI_MODULE_NAME ("rsxface") +ACPI_MODULE_NAME("rsxface") + +/* Local macros for 16,32-bit to 64-bit conversion */ +#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, info); \ + ACPI_COPY_FIELD(out, in, granularity); \ + ACPI_COPY_FIELD(out, in, minimum); \ + ACPI_COPY_FIELD(out, in, maximum); \ + ACPI_COPY_FIELD(out, in, translation_offset); \ + ACPI_COPY_FIELD(out, in, address_length); \ + ACPI_COPY_FIELD(out, in, resource_source); +/* Local prototypes */ +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); + +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node); + +/******************************************************************************* + * + * FUNCTION: acpi_rs_validate_parameters + * + * PARAMETERS: device_handle - Handle to a device + * Buffer - Pointer to a data buffer + * return_node - Pointer to where the device node is returned + * + * RETURN: Status + * + * DESCRIPTION: Common parameter validation for resource interfaces + * + ******************************************************************************/ + +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node) +{ + acpi_status status; + struct acpi_namespace_node *node; + + ACPI_FUNCTION_TRACE(rs_validate_parameters); + + /* + * Must have a valid handle to an ACPI device + */ + if (!device_handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + node = acpi_ns_map_handle_to_node(device_handle); + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + if (node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS(AE_TYPE); + } + + /* + * Validate the user buffer object + * + * 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 (later), so keep going. + */ + status = acpi_ut_validate_buffer(buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *return_node = node; + return_ACPI_STATUS(AE_OK); +} /******************************************************************************* * * 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 + * PARAMETERS: device_handle - Handle to the Bus device we are querying + * ret_buffer - 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 + * 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 @@ -73,50 +152,41 @@ ******************************************************************************/ acpi_status -acpi_get_irq_routing_table ( - acpi_handle device_handle, - struct acpi_buffer *ret_buffer) +acpi_get_irq_routing_table(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) { - acpi_status status; - + acpi_status status; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE ("acpi_get_irq_routing_table "); + ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); + /* Validate parameters then dispatch to internal routine */ - /* - * 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_rs_validate_parameters(device_handle, ret_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - 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); + status = acpi_rs_get_prt_method_data(node, ret_buffer); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) /******************************************************************************* * * FUNCTION: acpi_get_current_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * ret_buffer - a pointer to a buffer to receive the + * ret_buffer - 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 + * 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 @@ -126,304 +196,380 @@ acpi_get_irq_routing_table ( * the object indicated by the passed device_handle. * ******************************************************************************/ - acpi_status -acpi_get_current_resources ( - acpi_handle device_handle, - struct acpi_buffer *ret_buffer) +acpi_get_current_resources(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) { - acpi_status status; + acpi_status status; + struct acpi_namespace_node *node; + ACPI_FUNCTION_TRACE(acpi_get_current_resources); - ACPI_FUNCTION_TRACE ("acpi_get_current_resources"); + /* Validate parameters then dispatch to internal routine */ - - /* - * 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_validate_parameters(device_handle, ret_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - status = acpi_rs_get_crs_method_data (device_handle, ret_buffer); - return_ACPI_STATUS (status); + status = acpi_rs_get_crs_method_data(node, ret_buffer); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_current_resources) +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_get_possible_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * ret_buffer - a pointer to a buffer to receive the + * ret_buffer - 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 + * 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. * ******************************************************************************/ - acpi_status -acpi_get_possible_resources ( - acpi_handle device_handle, - struct acpi_buffer *ret_buffer) +acpi_get_possible_resources(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) { - acpi_status status; - + acpi_status status; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE ("acpi_get_possible_resources"); + ACPI_FUNCTION_TRACE(acpi_get_possible_resources); + /* Validate parameters then dispatch to internal routine */ - /* - * 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_rs_validate_parameters(device_handle, ret_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - 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); + status = acpi_rs_get_prs_method_data(node, ret_buffer); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * - * FUNCTION: acpi_walk_resources + * FUNCTION: acpi_set_current_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 + * PARAMETERS: device_handle - Handle to the device object for the + * device we are setting resources + * in_buffer - Pointer to a buffer containing the + * resources to be set for the device * * 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. + * 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_walk_resources ( - acpi_handle device_handle, - char *path, - ACPI_WALK_RESOURCE_CALLBACK user_function, - void *context) +acpi_set_current_resources(acpi_handle device_handle, + struct acpi_buffer *in_buffer) { - acpi_status status; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - struct acpi_resource *resource; - struct acpi_resource *buffer_end; + acpi_status status; + struct acpi_namespace_node *node; + ACPI_FUNCTION_TRACE(acpi_set_current_resources); - ACPI_FUNCTION_TRACE ("acpi_walk_resources"); + /* Validate the buffer, don't allow zero length */ - - 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); + if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_rs_get_method_data (device_handle, path, &buffer); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, in_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - /* Setup pointers */ + status = acpi_rs_set_srs_method_data(node, in_buffer); + return_ACPI_STATUS(status); +} - resource = (struct acpi_resource *) buffer.pointer; - buffer_end = ACPI_CAST_PTR (struct acpi_resource, - ((u8 *) buffer.pointer + buffer.length)); +ACPI_EXPORT_SYMBOL(acpi_set_current_resources) - /* Walk the resource list */ +/****************************************************************************** + * + * FUNCTION: acpi_resource_to_address64 + * + * PARAMETERS: Resource - Pointer to a resource + * Out - Pointer to the users's return buffer + * (a 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; - for (;;) { - if (!resource || resource->id == ACPI_RSTYPE_END_TAG) { - break; - } + if (!resource || !out) { + return (AE_BAD_PARAMETER); + } - status = user_function (resource, context); + /* Convert 16 or 32 address descriptor to 64 */ - switch (status) { - case AE_OK: - case AE_CTRL_DEPTH: + switch (resource->type) { + case ACPI_RESOURCE_TYPE_ADDRESS16: - /* Just keep going */ + address16 = (struct acpi_resource_address16 *)&resource->data; + ACPI_COPY_ADDRESS(out, address16); + break; - status = AE_OK; - break; + case ACPI_RESOURCE_TYPE_ADDRESS32: - case AE_CTRL_TERMINATE: + address32 = (struct acpi_resource_address32 *)&resource->data; + ACPI_COPY_ADDRESS(out, address32); + break; - /* Exit now, with OK stats */ + case ACPI_RESOURCE_TYPE_ADDRESS64: - status = AE_OK; - goto cleanup; + /* Simple copy for 64 bit source */ - default: + ACPI_MEMCPY(out, &resource->data, + sizeof(struct acpi_resource_address64)); + break; - /* All others are valid exceptions */ + default: + return (AE_BAD_PARAMETER); + } - goto cleanup; - } + return (AE_OK); +} - /* Get the next resource descriptor */ +ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) - resource = ACPI_NEXT_RESOURCE (resource); +/******************************************************************************* + * + * FUNCTION: acpi_get_vendor_resource + * + * PARAMETERS: device_handle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * ret_buffer - Where the vendor resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Walk a resource template for the specified evice to find a + * vendor-defined resource that matches the supplied UUID and + * UUID subtype. Returns a struct acpi_resource of type Vendor. + * + ******************************************************************************/ +acpi_status +acpi_get_vendor_resource(acpi_handle device_handle, + char *name, + struct acpi_vendor_uuid * uuid, + struct acpi_buffer * ret_buffer) +{ + struct acpi_vendor_walk_info info; + acpi_status status; - /* Check for end-of-buffer */ + /* Other parameters are validated by acpi_walk_resources */ - if (resource >= buffer_end) { - goto cleanup; - } + if (!uuid || !ret_buffer) { + return (AE_BAD_PARAMETER); } -cleanup: + info.uuid = uuid; + info.buffer = ret_buffer; + info.status = AE_NOT_EXIST; + + /* Walk the _CRS or _PRS resource list for this device */ + + status = + acpi_walk_resources(device_handle, name, + acpi_rs_match_vendor_resource, &info); + if (ACPI_FAILURE(status)) { + return (status); + } - acpi_os_free (buffer.pointer); - return_ACPI_STATUS (status); + return (info.status); } +ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) /******************************************************************************* * - * FUNCTION: acpi_set_current_resources + * FUNCTION: acpi_rs_match_vendor_resource * - * 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 + * PARAMETERS: acpi_walk_resource_callback * * 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. + * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID * ******************************************************************************/ - -acpi_status -acpi_set_current_resources ( - acpi_handle device_handle, - struct acpi_buffer *in_buffer) +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) { - acpi_status status; + struct acpi_vendor_walk_info *info = context; + struct acpi_resource_vendor_typed *vendor; + struct acpi_buffer *buffer; + acpi_status status; + /* Ignore all descriptors except Vendor */ - ACPI_FUNCTION_TRACE ("acpi_set_current_resources"); + if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { + return (AE_OK); + } + vendor = &resource->data.vendor_typed; /* - * Must have a valid handle and buffer + * For a valid match, these conditions must hold: + * + * 1) Length of descriptor data must be at least as long as a UUID struct + * 2) The UUID subtypes must match + * 3) The UUID data must match */ - if ((!device_handle) || - (!in_buffer) || - (!in_buffer->pointer) || - (!in_buffer->length)) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || + (vendor->uuid_subtype != info->uuid->subtype) || + (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { + return (AE_OK); } - status = acpi_rs_set_srs_method_data (device_handle, in_buffer); - return_ACPI_STATUS (status); -} + /* Validate/Allocate/Clear caller buffer */ + buffer = info->buffer; + status = acpi_ut_initialize_buffer(buffer, resource->length); + if (ACPI_FAILURE(status)) { + return (status); + } -#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); + /* Found the correct resource, copy and return it */ -/****************************************************************************** + ACPI_MEMCPY(buffer->pointer, resource, resource->length); + buffer->length = resource->length; + + /* Found the desired descriptor, terminate resource walk */ + + info->status = AE_OK; + return (AE_CTRL_TERMINATE); +} + +ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource) + +/******************************************************************************* * - * FUNCTION: acpi_resource_to_address64 + * FUNCTION: acpi_walk_resources * - * PARAMETERS: resource - Pointer to a resource - * out - Pointer to the users's return - * buffer (a struct - * struct acpi_resource_address64) + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * Name - 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: 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. + * 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_resource_to_address64 ( - struct acpi_resource *resource, - struct acpi_resource_address64 *out) +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) { - struct acpi_resource_address16 *address16; - struct acpi_resource_address32 *address32; + acpi_status status; + struct acpi_buffer buffer; + struct acpi_resource *resource; + struct acpi_resource *resource_end; + ACPI_FUNCTION_TRACE(acpi_walk_resources); - switch (resource->id) { - case ACPI_RSTYPE_ADDRESS16: + /* Parameter validation */ - address16 = (struct acpi_resource_address16 *) &resource->data; - ACPI_COPY_ADDRESS(out, address16); - break; + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + /* Get the _CRS or _PRS resource list */ - case ACPI_RSTYPE_ADDRESS32: + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - address32 = (struct acpi_resource_address32 *) &resource->data; - ACPI_COPY_ADDRESS(out, address32); - break; + /* Buffer now contains the resource list */ + resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource_end = + ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); - case ACPI_RSTYPE_ADDRESS64: + /* Walk the resource list until the end_tag is found (or buffer end) */ - /* Simple copy for 64 bit source */ + while (resource < resource_end) { - ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64)); - break; + /* Sanity check the resource */ + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } - default: - return (AE_BAD_PARAMETER); + /* Invoke the user function, abort on any error returned */ + + status = user_function(resource, context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_TERMINATE) { + + /* This is an OK termination by the user function */ + + status = AE_OK; + } + break; + } + + /* end_tag indicates end-of-list */ + + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + break; + } + + /* Get the next resource descriptor */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); } - return (AE_OK); + ACPI_FREE(buffer.pointer); + return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_walk_resources)