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 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_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 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 = (struct acpi_resource_address16 *)&resource->data; 342 ACPI_COPY_ADDRESS(out, address16); 343 break; 344 345 case ACPI_RESOURCE_TYPE_ADDRESS32: 346 347 address32 = (struct acpi_resource_address32 *)&resource->data; 348 ACPI_COPY_ADDRESS(out, address32); 349 break; 350 351 case ACPI_RESOURCE_TYPE_ADDRESS64: 352 353 /* Simple copy for 64 bit source */ 354 355 ACPI_MEMCPY(out, &resource->data, 356 sizeof(struct acpi_resource_address64)); 357 break; 358 359 default: 360 return (AE_BAD_PARAMETER); 361 } 362 363 return (AE_OK); 364 } 365 366 ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) 367 368 /******************************************************************************* 369 * 370 * FUNCTION: acpi_get_vendor_resource 371 * 372 * PARAMETERS: device_handle - Handle for the parent device object 373 * Name - Method name for the parent resource 374 * (METHOD_NAME__CRS or METHOD_NAME__PRS) 375 * Uuid - Pointer to the UUID to be matched. 376 * includes both subtype and 16-byte UUID 377 * ret_buffer - Where the vendor resource is returned 378 * 379 * RETURN: Status 380 * 381 * DESCRIPTION: Walk a resource template for the specified evice to find a 382 * vendor-defined resource that matches the supplied UUID and 383 * UUID subtype. Returns a struct acpi_resource of type Vendor. 384 * 385 ******************************************************************************/ 386 acpi_status 387 acpi_get_vendor_resource(acpi_handle device_handle, 388 char *name, 389 struct acpi_vendor_uuid * uuid, 390 struct acpi_buffer * ret_buffer) 391 { 392 struct acpi_vendor_walk_info info; 393 acpi_status status; 394 395 /* Other parameters are validated by acpi_walk_resources */ 396 397 if (!uuid || !ret_buffer) { 398 return (AE_BAD_PARAMETER); 399 } 400 401 info.uuid = uuid; 402 info.buffer = ret_buffer; 403 info.status = AE_NOT_EXIST; 404 405 /* Walk the _CRS or _PRS resource list for this device */ 406 407 status = 408 acpi_walk_resources(device_handle, name, 409 acpi_rs_match_vendor_resource, &info); 410 if (ACPI_FAILURE(status)) { 411 return (status); 412 } 413 414 return (info.status); 415 } 416 417 ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) 418 419 /******************************************************************************* 420 * 421 * FUNCTION: acpi_rs_match_vendor_resource 422 * 423 * PARAMETERS: acpi_walk_resource_callback 424 * 425 * RETURN: Status 426 * 427 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID 428 * 429 ******************************************************************************/ 430 static acpi_status 431 acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) 432 { 433 struct acpi_vendor_walk_info *info = context; 434 struct acpi_resource_vendor_typed *vendor; 435 struct acpi_buffer *buffer; 436 acpi_status status; 437 438 /* Ignore all descriptors except Vendor */ 439 440 if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { 441 return (AE_OK); 442 } 443 444 vendor = &resource->data.vendor_typed; 445 446 /* 447 * For a valid match, these conditions must hold: 448 * 449 * 1) Length of descriptor data must be at least as long as a UUID struct 450 * 2) The UUID subtypes must match 451 * 3) The UUID data must match 452 */ 453 if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || 454 (vendor->uuid_subtype != info->uuid->subtype) || 455 (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { 456 return (AE_OK); 457 } 458 459 /* Validate/Allocate/Clear caller buffer */ 460 461 buffer = info->buffer; 462 status = acpi_ut_initialize_buffer(buffer, resource->length); 463 if (ACPI_FAILURE(status)) { 464 return (status); 465 } 466 467 /* Found the correct resource, copy and return it */ 468 469 ACPI_MEMCPY(buffer->pointer, resource, resource->length); 470 buffer->length = resource->length; 471 472 /* Found the desired descriptor, terminate resource walk */ 473 474 info->status = AE_OK; 475 return (AE_CTRL_TERMINATE); 476 } 477 478 /******************************************************************************* 479 * 480 * FUNCTION: acpi_walk_resources 481 * 482 * PARAMETERS: device_handle - Handle to the device object for the 483 * device we are querying 484 * Name - Method name of the resources we want 485 * (METHOD_NAME__CRS or METHOD_NAME__PRS) 486 * user_function - Called for each resource 487 * Context - Passed to user_function 488 * 489 * RETURN: Status 490 * 491 * DESCRIPTION: Retrieves the current or possible resource list for the 492 * specified device. The user_function is called once for 493 * each resource in the list. 494 * 495 ******************************************************************************/ 496 acpi_status 497 acpi_walk_resources(acpi_handle device_handle, 498 char *name, 499 acpi_walk_resource_callback user_function, void *context) 500 { 501 acpi_status status; 502 struct acpi_buffer buffer; 503 struct acpi_resource *resource; 504 struct acpi_resource *resource_end; 505 506 ACPI_FUNCTION_TRACE(acpi_walk_resources); 507 508 /* Parameter validation */ 509 510 if (!device_handle || !user_function || !name || 511 (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && 512 !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { 513 return_ACPI_STATUS(AE_BAD_PARAMETER); 514 } 515 516 /* Get the _CRS or _PRS resource list */ 517 518 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 519 status = acpi_rs_get_method_data(device_handle, name, &buffer); 520 if (ACPI_FAILURE(status)) { 521 return_ACPI_STATUS(status); 522 } 523 524 /* Buffer now contains the resource list */ 525 526 resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); 527 resource_end = 528 ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); 529 530 /* Walk the resource list until the end_tag is found (or buffer end) */ 531 532 while (resource < resource_end) { 533 534 /* Sanity check the resource */ 535 536 if (resource->type > ACPI_RESOURCE_TYPE_MAX) { 537 status = AE_AML_INVALID_RESOURCE_TYPE; 538 break; 539 } 540 541 /* Invoke the user function, abort on any error returned */ 542 543 status = user_function(resource, context); 544 if (ACPI_FAILURE(status)) { 545 if (status == AE_CTRL_TERMINATE) { 546 547 /* This is an OK termination by the user function */ 548 549 status = AE_OK; 550 } 551 break; 552 } 553 554 /* end_tag indicates end-of-list */ 555 556 if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { 557 break; 558 } 559 560 /* Get the next resource descriptor */ 561 562 resource = 563 ACPI_ADD_PTR(struct acpi_resource, resource, 564 resource->length); 565 } 566 567 ACPI_FREE(buffer.pointer); 568 return_ACPI_STATUS(status); 569 } 570 571 ACPI_EXPORT_SYMBOL(acpi_walk_resources) 572