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