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