1 /******************************************************************************* 2 * 3 * Module Name: rsxface - Public interfaces to the resource manager 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2010, 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 50 ACPI_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 */ 68 static acpi_status 69 acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); 70 71 static acpi_status 72 acpi_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 90 static acpi_status 91 acpi_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_validate_handle(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 155 acpi_status 156 acpi_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 175 ACPI_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 ******************************************************************************/ 200 acpi_status 201 acpi_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 220 ACPI_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 ******************************************************************************/ 242 acpi_status 243 acpi_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 262 ACPI_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 ******************************************************************************/ 281 acpi_status 282 acpi_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 307 ACPI_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 ******************************************************************************/ 325 acpi_status 326 acpi_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 370 ACPI_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 ******************************************************************************/ 390 acpi_status 391 acpi_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 421 ACPI_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 ******************************************************************************/ 434 static acpi_status 435 acpi_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 ******************************************************************************/ 500 acpi_status 501 acpi_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 575 ACPI_EXPORT_SYMBOL(acpi_walk_resources) 576