1/******************************************************************************* 2 * 3 * Module Name: rsmisc - Miscellaneous resource descriptors 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 47#define _COMPONENT ACPI_RESOURCES 48ACPI_MODULE_NAME("rsmisc") 49#define INIT_RESOURCE_TYPE(i) i->resource_offset 50#define INIT_RESOURCE_LENGTH(i) i->aml_offset 51#define INIT_TABLE_LENGTH(i) i->value 52#define COMPARE_OPCODE(i) i->resource_offset 53#define COMPARE_TARGET(i) i->aml_offset 54#define COMPARE_VALUE(i) i->value 55/******************************************************************************* 56 * 57 * FUNCTION: acpi_rs_convert_aml_to_resource 58 * 59 * PARAMETERS: Resource - Pointer to the resource descriptor 60 * Aml - Where the AML descriptor is returned 61 * Info - Pointer to appropriate conversion table 62 * 63 * RETURN: Status 64 * 65 * DESCRIPTION: Convert an external AML resource descriptor to the corresponding 66 * internal resource descriptor 67 * 68 ******************************************************************************/ 69acpi_status 70acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, 71 union aml_resource *aml, 72 struct acpi_rsconvert_info *info) 73{ 74 acpi_rs_length aml_resource_length; 75 void *source; 76 void *destination; 77 char *target; 78 u8 count; 79 u8 flags_mode = FALSE; 80 u16 item_count = 0; 81 u16 temp16 = 0; 82 83 ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); 84 85 if (((acpi_native_uint) resource) & 0x3) { 86 87 /* Each internal resource struct is expected to be 32-bit aligned */ 88 89 ACPI_WARNING((AE_INFO, 90 "Misaligned resource pointer (get): %p Type %2.2X Len %X", 91 resource, resource->type, resource->length)); 92 } 93 94 /* Extract the resource Length field (does not include header length) */ 95 96 aml_resource_length = acpi_ut_get_resource_length(aml); 97 98 /* 99 * First table entry must be ACPI_RSC_INITxxx and must contain the 100 * table length (# of table entries) 101 */ 102 count = INIT_TABLE_LENGTH(info); 103 104 while (count) { 105 /* 106 * Source is the external AML byte stream buffer, 107 * destination is the internal resource descriptor 108 */ 109 source = ACPI_ADD_PTR(void, aml, info->aml_offset); 110 destination = 111 ACPI_ADD_PTR(void, resource, info->resource_offset); 112 113 switch (info->opcode) { 114 case ACPI_RSC_INITGET: 115 /* 116 * Get the resource type and the initial (minimum) length 117 */ 118 ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info)); 119 resource->type = INIT_RESOURCE_TYPE(info); 120 resource->length = INIT_RESOURCE_LENGTH(info); 121 break; 122 123 case ACPI_RSC_INITSET: 124 break; 125 126 case ACPI_RSC_FLAGINIT: 127 128 flags_mode = TRUE; 129 break; 130 131 case ACPI_RSC_1BITFLAG: 132 /* 133 * Mask and shift the flag bit 134 */ 135 ACPI_SET8(destination) = (u8) 136 ((ACPI_GET8(source) >> info->value) & 0x01); 137 break; 138 139 case ACPI_RSC_2BITFLAG: 140 /* 141 * Mask and shift the flag bits 142 */ 143 ACPI_SET8(destination) = (u8) 144 ((ACPI_GET8(source) >> info->value) & 0x03); 145 break; 146 147 case ACPI_RSC_COUNT: 148 149 item_count = ACPI_GET8(source); 150 ACPI_SET8(destination) = (u8) item_count; 151 152 resource->length = resource->length + 153 (info->value * (item_count - 1)); 154 break; 155 156 case ACPI_RSC_COUNT16: 157 158 item_count = aml_resource_length; 159 ACPI_SET16(destination) = item_count; 160 161 resource->length = resource->length + 162 (info->value * (item_count - 1)); 163 break; 164 165 case ACPI_RSC_LENGTH: 166 167 resource->length = resource->length + info->value; 168 break; 169 170 case ACPI_RSC_MOVE8: 171 case ACPI_RSC_MOVE16: 172 case ACPI_RSC_MOVE32: 173 case ACPI_RSC_MOVE64: 174 /* 175 * Raw data move. Use the Info value field unless item_count has 176 * been previously initialized via a COUNT opcode 177 */ 178 if (info->value) { 179 item_count = info->value; 180 } 181 acpi_rs_move_data(destination, source, item_count, 182 info->opcode); 183 break; 184 185 case ACPI_RSC_SET8: 186 187 ACPI_MEMSET(destination, info->aml_offset, info->value); 188 break; 189 190 case ACPI_RSC_DATA8: 191 192 target = ACPI_ADD_PTR(char, resource, info->value); 193 ACPI_MEMCPY(destination, source, ACPI_GET16(target)); 194 break; 195 196 case ACPI_RSC_ADDRESS: 197 /* 198 * Common handler for address descriptor flags 199 */ 200 if (!acpi_rs_get_address_common(resource, aml)) { 201 return_ACPI_STATUS 202 (AE_AML_INVALID_RESOURCE_TYPE); 203 } 204 break; 205 206 case ACPI_RSC_SOURCE: 207 /* 208 * Optional resource_source (Index and String) 209 */ 210 resource->length += 211 acpi_rs_get_resource_source(aml_resource_length, 212 info->value, 213 destination, aml, NULL); 214 break; 215 216 case ACPI_RSC_SOURCEX: 217 /* 218 * Optional resource_source (Index and String). This is the more 219 * complicated case used by the Interrupt() macro 220 */ 221 target = 222 ACPI_ADD_PTR(char, resource, 223 info->aml_offset + (item_count * 4)); 224 225 resource->length += 226 acpi_rs_get_resource_source(aml_resource_length, 227 (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); 228 break; 229 230 case ACPI_RSC_BITMASK: 231 /* 232 * 8-bit encoded bitmask (DMA macro) 233 */ 234 item_count = 235 acpi_rs_decode_bitmask(ACPI_GET8(source), 236 destination); 237 if (item_count) { 238 resource->length += (item_count - 1); 239 } 240 241 target = ACPI_ADD_PTR(char, resource, info->value); 242 ACPI_SET8(target) = (u8) item_count; 243 break; 244 245 case ACPI_RSC_BITMASK16: 246 /* 247 * 16-bit encoded bitmask (IRQ macro) 248 */ 249 ACPI_MOVE_16_TO_16(&temp16, source); 250 251 item_count = 252 acpi_rs_decode_bitmask(temp16, destination); 253 if (item_count) { 254 resource->length += (item_count - 1); 255 } 256 257 target = ACPI_ADD_PTR(char, resource, info->value); 258 ACPI_SET8(target) = (u8) item_count; 259 break; 260 261 case ACPI_RSC_EXIT_NE: 262 /* 263 * Control - Exit conversion if not equal 264 */ 265 switch (info->resource_offset) { 266 case ACPI_RSC_COMPARE_AML_LENGTH: 267 if (aml_resource_length != info->value) { 268 goto exit; 269 } 270 break; 271 272 case ACPI_RSC_COMPARE_VALUE: 273 if (ACPI_GET8(source) != info->value) { 274 goto exit; 275 } 276 break; 277 278 default: 279 280 ACPI_ERROR((AE_INFO, 281 "Invalid conversion sub-opcode")); 282 return_ACPI_STATUS(AE_BAD_PARAMETER); 283 } 284 break; 285 286 default: 287 288 ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); 289 return_ACPI_STATUS(AE_BAD_PARAMETER); 290 } 291 292 count--; 293 info++; 294 } 295 296 exit: 297 if (!flags_mode) { 298 299 /* Round the resource struct length up to the next boundary (32 or 64) */ 300 301 resource->length = 302 (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); 303 } 304 return_ACPI_STATUS(AE_OK); 305} 306 307/******************************************************************************* 308 * 309 * FUNCTION: acpi_rs_convert_resource_to_aml 310 * 311 * PARAMETERS: Resource - Pointer to the resource descriptor 312 * Aml - Where the AML descriptor is returned 313 * Info - Pointer to appropriate conversion table 314 * 315 * RETURN: Status 316 * 317 * DESCRIPTION: Convert an internal resource descriptor to the corresponding 318 * external AML resource descriptor. 319 * 320 ******************************************************************************/ 321 322acpi_status 323acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, 324 union aml_resource *aml, 325 struct acpi_rsconvert_info *info) 326{ 327 void *source = NULL; 328 void *destination; 329 acpi_rsdesc_size aml_length = 0; 330 u8 count; 331 u16 temp16 = 0; 332 u16 item_count = 0; 333 334 ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); 335 336 /* 337 * First table entry must be ACPI_RSC_INITxxx and must contain the 338 * table length (# of table entries) 339 */ 340 count = INIT_TABLE_LENGTH(info); 341 342 while (count) { 343 /* 344 * Source is the internal resource descriptor, 345 * destination is the external AML byte stream buffer 346 */ 347 source = ACPI_ADD_PTR(void, resource, info->resource_offset); 348 destination = ACPI_ADD_PTR(void, aml, info->aml_offset); 349 350 switch (info->opcode) { 351 case ACPI_RSC_INITSET: 352 353 ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info)); 354 aml_length = INIT_RESOURCE_LENGTH(info); 355 acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), 356 aml_length, aml); 357 break; 358 359 case ACPI_RSC_INITGET: 360 break; 361 362 case ACPI_RSC_FLAGINIT: 363 /* 364 * Clear the flag byte 365 */ 366 ACPI_SET8(destination) = 0; 367 break; 368 369 case ACPI_RSC_1BITFLAG: 370 /* 371 * Mask and shift the flag bit 372 */ 373 ACPI_SET8(destination) |= (u8) 374 ((ACPI_GET8(source) & 0x01) << info->value); 375 break; 376 377 case ACPI_RSC_2BITFLAG: 378 /* 379 * Mask and shift the flag bits 380 */ 381 ACPI_SET8(destination) |= (u8) 382 ((ACPI_GET8(source) & 0x03) << info->value); 383 break; 384 385 case ACPI_RSC_COUNT: 386 387 item_count = ACPI_GET8(source); 388 ACPI_SET8(destination) = (u8) item_count; 389 390 aml_length = 391 (u16) (aml_length + 392 (info->value * (item_count - 1))); 393 break; 394 395 case ACPI_RSC_COUNT16: 396 397 item_count = ACPI_GET16(source); 398 aml_length = (u16) (aml_length + item_count); 399 acpi_rs_set_resource_length(aml_length, aml); 400 break; 401 402 case ACPI_RSC_LENGTH: 403 404 acpi_rs_set_resource_length(info->value, aml); 405 break; 406 407 case ACPI_RSC_MOVE8: 408 case ACPI_RSC_MOVE16: 409 case ACPI_RSC_MOVE32: 410 case ACPI_RSC_MOVE64: 411 412 if (info->value) { 413 item_count = info->value; 414 } 415 acpi_rs_move_data(destination, source, item_count, 416 info->opcode); 417 break; 418 419 case ACPI_RSC_ADDRESS: 420 421 /* Set the Resource Type, General Flags, and Type-Specific Flags */ 422 423 acpi_rs_set_address_common(aml, resource); 424 break; 425 426 case ACPI_RSC_SOURCEX: 427 /* 428 * Optional resource_source (Index and String) 429 */ 430 aml_length = 431 acpi_rs_set_resource_source(aml, (acpi_rs_length) 432 aml_length, source); 433 acpi_rs_set_resource_length(aml_length, aml); 434 break; 435 436 case ACPI_RSC_SOURCE: 437 /* 438 * Optional resource_source (Index and String). This is the more 439 * complicated case used by the Interrupt() macro 440 */ 441 aml_length = 442 acpi_rs_set_resource_source(aml, info->value, 443 source); 444 acpi_rs_set_resource_length(aml_length, aml); 445 break; 446 447 case ACPI_RSC_BITMASK: 448 /* 449 * 8-bit encoded bitmask (DMA macro) 450 */ 451 ACPI_SET8(destination) = (u8) 452 acpi_rs_encode_bitmask(source, 453 *ACPI_ADD_PTR(u8, resource, 454 info->value)); 455 break; 456 457 case ACPI_RSC_BITMASK16: 458 /* 459 * 16-bit encoded bitmask (IRQ macro) 460 */ 461 temp16 = acpi_rs_encode_bitmask(source, 462 *ACPI_ADD_PTR(u8, 463 resource, 464 info-> 465 value)); 466 ACPI_MOVE_16_TO_16(destination, &temp16); 467 break; 468 469 case ACPI_RSC_EXIT_LE: 470 /* 471 * Control - Exit conversion if less than or equal 472 */ 473 if (item_count <= info->value) { 474 goto exit; 475 } 476 break; 477 478 case ACPI_RSC_EXIT_NE: 479 /* 480 * Control - Exit conversion if not equal 481 */ 482 switch (COMPARE_OPCODE(info)) { 483 case ACPI_RSC_COMPARE_VALUE: 484 485 if (*ACPI_ADD_PTR(u8, resource, 486 COMPARE_TARGET(info)) != 487 COMPARE_VALUE(info)) { 488 goto exit; 489 } 490 break; 491 492 default: 493 494 ACPI_ERROR((AE_INFO, 495 "Invalid conversion sub-opcode")); 496 return_ACPI_STATUS(AE_BAD_PARAMETER); 497 } 498 break; 499 500 default: 501 502 ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); 503 return_ACPI_STATUS(AE_BAD_PARAMETER); 504 } 505 506 count--; 507 info++; 508 } 509 510 exit: 511 return_ACPI_STATUS(AE_OK); 512} 513