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