linux/drivers/acpi/acpica/rsxface.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Module Name: rsxface - Public interfaces to the resource manager
   4 *
   5 ******************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2008, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acresrc.h"
  47#include "acnamesp.h"
  48
  49#define _COMPONENT          ACPI_RESOURCES
  50ACPI_MODULE_NAME("rsxface")
  51
  52/* Local macros for 16,32-bit to 64-bit conversion */
  53#define ACPI_COPY_FIELD(out, in, field)  ((out)->field = (in)->field)
  54#define ACPI_COPY_ADDRESS(out, in)                      \
  55        ACPI_COPY_FIELD(out, in, resource_type);             \
  56        ACPI_COPY_FIELD(out, in, producer_consumer);         \
  57        ACPI_COPY_FIELD(out, in, decode);                    \
  58        ACPI_COPY_FIELD(out, in, min_address_fixed);         \
  59        ACPI_COPY_FIELD(out, in, max_address_fixed);         \
  60        ACPI_COPY_FIELD(out, in, info);                      \
  61        ACPI_COPY_FIELD(out, in, granularity);               \
  62        ACPI_COPY_FIELD(out, in, minimum);                   \
  63        ACPI_COPY_FIELD(out, in, maximum);                   \
  64        ACPI_COPY_FIELD(out, in, translation_offset);        \
  65        ACPI_COPY_FIELD(out, in, address_length);            \
  66        ACPI_COPY_FIELD(out, in, resource_source);
  67/* Local prototypes */
  68static acpi_status
  69acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
  70
  71static acpi_status
  72acpi_rs_validate_parameters(acpi_handle device_handle,
  73                            struct acpi_buffer *buffer,
  74                            struct acpi_namespace_node **return_node);
  75
  76/*******************************************************************************
  77 *
  78 * FUNCTION:    acpi_rs_validate_parameters
  79 *
  80 * PARAMETERS:  device_handle   - Handle to a device
  81 *              Buffer          - Pointer to a data buffer
  82 *              return_node     - Pointer to where the device node is returned
  83 *
  84 * RETURN:      Status
  85 *
  86 * DESCRIPTION: Common parameter validation for resource interfaces
  87 *
  88 ******************************************************************************/
  89
  90static acpi_status
  91acpi_rs_validate_parameters(acpi_handle device_handle,
  92                            struct acpi_buffer *buffer,
  93                            struct acpi_namespace_node **return_node)
  94{
  95        acpi_status status;
  96        struct acpi_namespace_node *node;
  97
  98        ACPI_FUNCTION_TRACE(rs_validate_parameters);
  99
 100        /*
 101         * Must have a valid handle to an ACPI device
 102         */
 103        if (!device_handle) {
 104                return_ACPI_STATUS(AE_BAD_PARAMETER);
 105        }
 106
 107        node = acpi_ns_map_handle_to_node(device_handle);
 108        if (!node) {
 109                return_ACPI_STATUS(AE_BAD_PARAMETER);
 110        }
 111
 112        if (node->type != ACPI_TYPE_DEVICE) {
 113                return_ACPI_STATUS(AE_TYPE);
 114        }
 115
 116        /*
 117         * Validate the user buffer object
 118         *
 119         * if there is a non-zero buffer length we also need a valid pointer in
 120         * the buffer. If it's a zero buffer length, we'll be returning the
 121         * needed buffer size (later), so keep going.
 122         */
 123        status = acpi_ut_validate_buffer(buffer);
 124        if (ACPI_FAILURE(status)) {
 125                return_ACPI_STATUS(status);
 126        }
 127
 128        *return_node = node;
 129        return_ACPI_STATUS(AE_OK);
 130}
 131
 132/*******************************************************************************
 133 *
 134 * FUNCTION:    acpi_get_irq_routing_table
 135 *
 136 * PARAMETERS:  device_handle   - Handle to the Bus device we are querying
 137 *              ret_buffer      - Pointer to a buffer to receive the
 138 *                                current resources for the device
 139 *
 140 * RETURN:      Status
 141 *
 142 * DESCRIPTION: This function is called to get the IRQ routing table for a
 143 *              specific bus. The caller must first acquire a handle for the
 144 *              desired bus. The routine table is placed in the buffer pointed
 145 *              to by the ret_buffer variable parameter.
 146 *
 147 *              If the function fails an appropriate status will be returned
 148 *              and the value of ret_buffer is undefined.
 149 *
 150 *              This function attempts to execute the _PRT method contained in
 151 *              the object indicated by the passed device_handle.
 152 *
 153 ******************************************************************************/
 154
 155acpi_status
 156acpi_get_irq_routing_table(acpi_handle device_handle,
 157                           struct acpi_buffer *ret_buffer)
 158{
 159        acpi_status status;
 160        struct acpi_namespace_node *node;
 161
 162        ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);
 163
 164        /* Validate parameters then dispatch to internal routine */
 165
 166        status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
 167        if (ACPI_FAILURE(status)) {
 168                return_ACPI_STATUS(status);
 169        }
 170
 171        status = acpi_rs_get_prt_method_data(node, ret_buffer);
 172        return_ACPI_STATUS(status);
 173}
 174
 175ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)
 176
 177/*******************************************************************************
 178 *
 179 * FUNCTION:    acpi_get_current_resources
 180 *
 181 * PARAMETERS:  device_handle   - Handle to the device object for the
 182 *                                device we are querying
 183 *              ret_buffer      - Pointer to a buffer to receive the
 184 *                                current resources for the device
 185 *
 186 * RETURN:      Status
 187 *
 188 * DESCRIPTION: This function is called to get the current resources for a
 189 *              specific device. The caller must first acquire a handle for
 190 *              the desired device. The resource data is placed in the buffer
 191 *              pointed to by the ret_buffer variable parameter.
 192 *
 193 *              If the function fails an appropriate status will be returned
 194 *              and the value of ret_buffer is undefined.
 195 *
 196 *              This function attempts to execute the _CRS method contained in
 197 *              the object indicated by the passed device_handle.
 198 *
 199 ******************************************************************************/
 200acpi_status
 201acpi_get_current_resources(acpi_handle device_handle,
 202                           struct acpi_buffer *ret_buffer)
 203{
 204        acpi_status status;
 205        struct acpi_namespace_node *node;
 206
 207        ACPI_FUNCTION_TRACE(acpi_get_current_resources);
 208
 209        /* Validate parameters then dispatch to internal routine */
 210
 211        status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
 212        if (ACPI_FAILURE(status)) {
 213                return_ACPI_STATUS(status);
 214        }
 215
 216        status = acpi_rs_get_crs_method_data(node, ret_buffer);
 217        return_ACPI_STATUS(status);
 218}
 219
 220ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
 221#ifdef ACPI_FUTURE_USAGE
 222/*******************************************************************************
 223 *
 224 * FUNCTION:    acpi_get_possible_resources
 225 *
 226 * PARAMETERS:  device_handle   - Handle to the device object for the
 227 *                                device we are querying
 228 *              ret_buffer      - Pointer to a buffer to receive the
 229 *                                resources for the device
 230 *
 231 * RETURN:      Status
 232 *
 233 * DESCRIPTION: This function is called to get a list of the possible resources
 234 *              for a specific device. The caller must first acquire a handle
 235 *              for the desired device. The resource data is placed in the
 236 *              buffer pointed to by the ret_buffer variable.
 237 *
 238 *              If the function fails an appropriate status will be returned
 239 *              and the value of ret_buffer is undefined.
 240 *
 241 ******************************************************************************/
 242acpi_status
 243acpi_get_possible_resources(acpi_handle device_handle,
 244                            struct acpi_buffer *ret_buffer)
 245{
 246        acpi_status status;
 247        struct acpi_namespace_node *node;
 248
 249        ACPI_FUNCTION_TRACE(acpi_get_possible_resources);
 250
 251        /* Validate parameters then dispatch to internal routine */
 252
 253        status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
 254        if (ACPI_FAILURE(status)) {
 255                return_ACPI_STATUS(status);
 256        }
 257
 258        status = acpi_rs_get_prs_method_data(node, ret_buffer);
 259        return_ACPI_STATUS(status);
 260}
 261
 262ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
 263#endif                          /*  ACPI_FUTURE_USAGE  */
 264/*******************************************************************************
 265 *
 266 * FUNCTION:    acpi_set_current_resources
 267 *
 268 * PARAMETERS:  device_handle   - Handle to the device object for the
 269 *                                device we are setting resources
 270 *              in_buffer       - Pointer to a buffer containing the
 271 *                                resources to be set for the device
 272 *
 273 * RETURN:      Status
 274 *
 275 * DESCRIPTION: This function is called to set the current resources for a
 276 *              specific device. The caller must first acquire a handle for
 277 *              the desired device. The resource data is passed to the routine
 278 *              the buffer pointed to by the in_buffer variable.
 279 *
 280 ******************************************************************************/
 281acpi_status
 282acpi_set_current_resources(acpi_handle device_handle,
 283                           struct acpi_buffer *in_buffer)
 284{
 285        acpi_status status;
 286        struct acpi_namespace_node *node;
 287
 288        ACPI_FUNCTION_TRACE(acpi_set_current_resources);
 289
 290        /* Validate the buffer, don't allow zero length */
 291
 292        if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
 293                return_ACPI_STATUS(AE_BAD_PARAMETER);
 294        }
 295
 296        /* Validate parameters then dispatch to internal routine */
 297
 298        status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);
 299        if (ACPI_FAILURE(status)) {
 300                return_ACPI_STATUS(status);
 301        }
 302
 303        status = acpi_rs_set_srs_method_data(node, in_buffer);
 304        return_ACPI_STATUS(status);
 305}
 306
 307ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
 308
 309/******************************************************************************
 310 *
 311 * FUNCTION:    acpi_resource_to_address64
 312 *
 313 * PARAMETERS:  Resource        - Pointer to a resource
 314 *              Out             - Pointer to the users's return buffer
 315 *                                (a struct acpi_resource_address64)
 316 *
 317 * RETURN:      Status
 318 *
 319 * DESCRIPTION: If the resource is an address16, address32, or address64,
 320 *              copy it to the address64 return buffer. This saves the
 321 *              caller from having to duplicate code for different-sized
 322 *              addresses.
 323 *
 324 ******************************************************************************/
 325acpi_status
 326acpi_resource_to_address64(struct acpi_resource *resource,
 327                           struct acpi_resource_address64 *out)
 328{
 329        struct acpi_resource_address16 *address16;
 330        struct acpi_resource_address32 *address32;
 331
 332        if (!resource || !out) {
 333                return (AE_BAD_PARAMETER);
 334        }
 335
 336        /* Convert 16 or 32 address descriptor to 64 */
 337
 338        switch (resource->type) {
 339        case ACPI_RESOURCE_TYPE_ADDRESS16:
 340
 341                address16 =
 342                    ACPI_CAST_PTR(struct acpi_resource_address16,
 343                                  &resource->data);
 344                ACPI_COPY_ADDRESS(out, address16);
 345                break;
 346
 347        case ACPI_RESOURCE_TYPE_ADDRESS32:
 348
 349                address32 =
 350                    ACPI_CAST_PTR(struct acpi_resource_address32,
 351                                  &resource->data);
 352                ACPI_COPY_ADDRESS(out, address32);
 353                break;
 354
 355        case ACPI_RESOURCE_TYPE_ADDRESS64:
 356
 357                /* Simple copy for 64 bit source */
 358
 359                ACPI_MEMCPY(out, &resource->data,
 360                            sizeof(struct acpi_resource_address64));
 361                break;
 362
 363        default:
 364                return (AE_BAD_PARAMETER);
 365        }
 366
 367        return (AE_OK);
 368}
 369
 370ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)
 371
 372/*******************************************************************************
 373 *
 374 * FUNCTION:    acpi_get_vendor_resource
 375 *
 376 * PARAMETERS:  device_handle   - Handle for the parent device object
 377 *              Name            - Method name for the parent resource
 378 *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
 379 *              Uuid            - Pointer to the UUID to be matched.
 380 *                                includes both subtype and 16-byte UUID
 381 *              ret_buffer      - Where the vendor resource is returned
 382 *
 383 * RETURN:      Status
 384 *
 385 * DESCRIPTION: Walk a resource template for the specified evice to find a
 386 *              vendor-defined resource that matches the supplied UUID and
 387 *              UUID subtype. Returns a struct acpi_resource of type Vendor.
 388 *
 389 ******************************************************************************/
 390acpi_status
 391acpi_get_vendor_resource(acpi_handle device_handle,
 392                         char *name,
 393                         struct acpi_vendor_uuid * uuid,
 394                         struct acpi_buffer * ret_buffer)
 395{
 396        struct acpi_vendor_walk_info info;
 397        acpi_status status;
 398
 399        /* Other parameters are validated by acpi_walk_resources */
 400
 401        if (!uuid || !ret_buffer) {
 402                return (AE_BAD_PARAMETER);
 403        }
 404
 405        info.uuid = uuid;
 406        info.buffer = ret_buffer;
 407        info.status = AE_NOT_EXIST;
 408
 409        /* Walk the _CRS or _PRS resource list for this device */
 410
 411        status =
 412            acpi_walk_resources(device_handle, name,
 413                                acpi_rs_match_vendor_resource, &info);
 414        if (ACPI_FAILURE(status)) {
 415                return (status);
 416        }
 417
 418        return (info.status);
 419}
 420
 421ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)
 422
 423/*******************************************************************************
 424 *
 425 * FUNCTION:    acpi_rs_match_vendor_resource
 426 *
 427 * PARAMETERS:  acpi_walk_resource_callback
 428 *
 429 * RETURN:      Status
 430 *
 431 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
 432 *
 433 ******************************************************************************/
 434static acpi_status
 435acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
 436{
 437        struct acpi_vendor_walk_info *info = context;
 438        struct acpi_resource_vendor_typed *vendor;
 439        struct acpi_buffer *buffer;
 440        acpi_status status;
 441
 442        /* Ignore all descriptors except Vendor */
 443
 444        if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
 445                return (AE_OK);
 446        }
 447
 448        vendor = &resource->data.vendor_typed;
 449
 450        /*
 451         * For a valid match, these conditions must hold:
 452         *
 453         * 1) Length of descriptor data must be at least as long as a UUID struct
 454         * 2) The UUID subtypes must match
 455         * 3) The UUID data must match
 456         */
 457        if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
 458            (vendor->uuid_subtype != info->uuid->subtype) ||
 459            (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
 460                return (AE_OK);
 461        }
 462
 463        /* Validate/Allocate/Clear caller buffer */
 464
 465        buffer = info->buffer;
 466        status = acpi_ut_initialize_buffer(buffer, resource->length);
 467        if (ACPI_FAILURE(status)) {
 468                return (status);
 469        }
 470
 471        /* Found the correct resource, copy and return it */
 472
 473        ACPI_MEMCPY(buffer->pointer, resource, resource->length);
 474        buffer->length = resource->length;
 475
 476        /* Found the desired descriptor, terminate resource walk */
 477
 478        info->status = AE_OK;
 479        return (AE_CTRL_TERMINATE);
 480}
 481
 482/*******************************************************************************
 483 *
 484 * FUNCTION:    acpi_walk_resources
 485 *
 486 * PARAMETERS:  device_handle   - Handle to the device object for the
 487 *                                device we are querying
 488 *              Name            - Method name of the resources we want
 489 *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
 490 *              user_function   - Called for each resource
 491 *              Context         - Passed to user_function
 492 *
 493 * RETURN:      Status
 494 *
 495 * DESCRIPTION: Retrieves the current or possible resource list for the
 496 *              specified device. The user_function is called once for
 497 *              each resource in the list.
 498 *
 499 ******************************************************************************/
 500acpi_status
 501acpi_walk_resources(acpi_handle device_handle,
 502                    char *name,
 503                    acpi_walk_resource_callback user_function, void *context)
 504{
 505        acpi_status status;
 506        struct acpi_buffer buffer;
 507        struct acpi_resource *resource;
 508        struct acpi_resource *resource_end;
 509
 510        ACPI_FUNCTION_TRACE(acpi_walk_resources);
 511
 512        /* Parameter validation */
 513
 514        if (!device_handle || !user_function || !name ||
 515            (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
 516             !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) {
 517                return_ACPI_STATUS(AE_BAD_PARAMETER);
 518        }
 519
 520        /* Get the _CRS or _PRS resource list */
 521
 522        buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
 523        status = acpi_rs_get_method_data(device_handle, name, &buffer);
 524        if (ACPI_FAILURE(status)) {
 525                return_ACPI_STATUS(status);
 526        }
 527
 528        /* Buffer now contains the resource list */
 529
 530        resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
 531        resource_end =
 532            ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
 533
 534        /* Walk the resource list until the end_tag is found (or buffer end) */
 535
 536        while (resource < resource_end) {
 537
 538                /* Sanity check the resource */
 539
 540                if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
 541                        status = AE_AML_INVALID_RESOURCE_TYPE;
 542                        break;
 543                }
 544
 545                /* Invoke the user function, abort on any error returned */
 546
 547                status = user_function(resource, context);
 548                if (ACPI_FAILURE(status)) {
 549                        if (status == AE_CTRL_TERMINATE) {
 550
 551                                /* This is an OK termination by the user function */
 552
 553                                status = AE_OK;
 554                        }
 555                        break;
 556                }
 557
 558                /* end_tag indicates end-of-list */
 559
 560                if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
 561                        break;
 562                }
 563
 564                /* Get the next resource descriptor */
 565
 566                resource =
 567                    ACPI_ADD_PTR(struct acpi_resource, resource,
 568                                 resource->length);
 569        }
 570
 571        ACPI_FREE(buffer.pointer);
 572        return_ACPI_STATUS(status);
 573}
 574
 575ACPI_EXPORT_SYMBOL(acpi_walk_resources)
 576