1/****************************************************************************** 2 * 3 * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 4 * $Revision: 1.1.1.1 $ 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000, 2001 R. Byron Moore 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 27#include "acpi.h" 28#include "acdispat.h" 29#include "acinterp.h" 30#include "amlcode.h" 31#include "acnamesp.h" 32#include "achware.h" 33#include "acevents.h" 34 35 36#define _COMPONENT ACPI_EXECUTER 37 MODULE_NAME ("exfield") 38 39 40/******************************************************************************* 41 * 42 * FUNCTION: Acpi_ex_read_data_from_field 43 * 44 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 45 * *Field_node - Parent node for field to be accessed 46 * *Buffer - Value(s) to be read or written 47 * Buffer_length - Number of bytes to transfer 48 * 49 * RETURN: Status3 50 * 51 * DESCRIPTION: Read or write a named field 52 * 53 ******************************************************************************/ 54 55acpi_status 56acpi_ex_read_data_from_field ( 57 acpi_operand_object *obj_desc, 58 acpi_operand_object **ret_buffer_desc) 59{ 60 acpi_status status; 61 acpi_operand_object *buffer_desc; 62 u32 length; 63 void *buffer; 64 65 66 FUNCTION_TRACE_PTR ("Ex_read_data_from_field", obj_desc); 67 68 69 /* Parameter validation */ 70 71 if (!obj_desc) { 72 return_ACPI_STATUS (AE_AML_NO_OPERAND); 73 } 74 75 /* 76 * Allocate a buffer for the contents of the field. 77 * 78 * If the field is larger than the size of an acpi_integer, create 79 * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 80 * the use of arithmetic operators on the returned value if the 81 * field size is equal or smaller than an Integer. 82 * 83 * Note: Field.length is in bits. 84 */ 85 length = ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length); 86 87 if (length > sizeof (acpi_integer)) { 88 /* Field is too large for an Integer, create a Buffer instead */ 89 90 buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); 91 if (!buffer_desc) { 92 return_ACPI_STATUS (AE_NO_MEMORY); 93 } 94 95 /* Create the actual read buffer */ 96 97 buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (length); 98 if (!buffer_desc->buffer.pointer) { 99 acpi_ut_remove_reference (buffer_desc); 100 return_ACPI_STATUS (AE_NO_MEMORY); 101 } 102 103 buffer_desc->buffer.length = length; 104 buffer = buffer_desc->buffer.pointer; 105 } 106 107 else { 108 /* Field will fit within an Integer (normal case) */ 109 110 buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 111 if (!buffer_desc) { 112 return_ACPI_STATUS (AE_NO_MEMORY); 113 } 114 115 length = sizeof (buffer_desc->integer.value); 116 buffer = &buffer_desc->integer.value; 117 } 118 119 120 /* Read from the appropriate field */ 121 122 switch (obj_desc->common.type) { 123 case ACPI_TYPE_BUFFER_FIELD: 124 status = acpi_ex_access_buffer_field (ACPI_READ, obj_desc, buffer, length); 125 break; 126 127 case INTERNAL_TYPE_REGION_FIELD: 128 status = acpi_ex_access_region_field (ACPI_READ, obj_desc, buffer, length); 129 break; 130 131 case INTERNAL_TYPE_BANK_FIELD: 132 status = acpi_ex_access_bank_field (ACPI_READ, obj_desc, buffer, length); 133 break; 134 135 case INTERNAL_TYPE_INDEX_FIELD: 136 status = acpi_ex_access_index_field (ACPI_READ, obj_desc, buffer, length); 137 break; 138 139 default: 140 status = AE_AML_INTERNAL; 141 } 142 143 144 if (ACPI_FAILURE (status)) { 145 acpi_ut_remove_reference (buffer_desc); 146 } 147 148 else if (ret_buffer_desc) { 149 *ret_buffer_desc = buffer_desc; 150 } 151 152 return_ACPI_STATUS (status); 153} 154 155 156/******************************************************************************* 157 * 158 * FUNCTION: Acpi_ex_write_data_to_field 159 * 160 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 161 * *Field_node - Parent node for field to be accessed 162 * *Buffer - Value(s) to be read or written 163 * Buffer_length - Number of bytes to transfer 164 * 165 * RETURN: Status 166 * 167 * DESCRIPTION: Read or write a named field 168 * 169 ******************************************************************************/ 170 171 172acpi_status 173acpi_ex_write_data_to_field ( 174 acpi_operand_object *source_desc, 175 acpi_operand_object *obj_desc) 176{ 177 acpi_status status; 178 u32 length; 179 void *buffer; 180 181 182 FUNCTION_TRACE_PTR ("Ex_write_data_to_field", obj_desc); 183 184 185 /* Parameter validation */ 186 187 if (!source_desc || !obj_desc) { 188 return_ACPI_STATUS (AE_AML_NO_OPERAND); 189 } 190 191 192 /* 193 * Get a pointer to the data to be written 194 */ 195 switch (source_desc->common.type) { 196 case ACPI_TYPE_INTEGER: 197 buffer = &source_desc->integer.value; 198 length = sizeof (source_desc->integer.value); 199 break; 200 201 case ACPI_TYPE_BUFFER: 202 buffer = source_desc->buffer.pointer; 203 length = source_desc->buffer.length; 204 break; 205 206 case ACPI_TYPE_STRING: 207 buffer = source_desc->string.pointer; 208 length = source_desc->string.length; 209 break; 210 211 default: 212 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 213 } 214 215 216 /* 217 * Decode the type of field to be written 218 */ 219 switch (obj_desc->common.type) { 220 case ACPI_TYPE_BUFFER_FIELD: 221 status = acpi_ex_access_buffer_field (ACPI_WRITE, obj_desc, buffer, length); 222 break; 223 224 case INTERNAL_TYPE_REGION_FIELD: 225 status = acpi_ex_access_region_field (ACPI_WRITE, obj_desc, buffer, length); 226 break; 227 228 case INTERNAL_TYPE_BANK_FIELD: 229 status = acpi_ex_access_bank_field (ACPI_WRITE, obj_desc, buffer, length); 230 break; 231 232 case INTERNAL_TYPE_INDEX_FIELD: 233 status = acpi_ex_access_index_field (ACPI_WRITE, obj_desc, buffer, length); 234 break; 235 236 default: 237 return_ACPI_STATUS (AE_AML_INTERNAL); 238 } 239 240 241 return_ACPI_STATUS (status); 242} 243 244 245/******************************************************************************* 246 * 247 * FUNCTION: Acpi_ex_access_buffer_field 248 * 249 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 250 * *Field_node - Parent node for field to be accessed 251 * *Buffer - Value(s) to be read or written 252 * Buffer_length - Number of bytes to transfer 253 * 254 * RETURN: Status 255 * 256 * DESCRIPTION: Read or write a named field 257 * 258 ******************************************************************************/ 259 260acpi_status 261acpi_ex_access_buffer_field ( 262 u32 mode, 263 acpi_operand_object *obj_desc, 264 void *buffer, 265 u32 buffer_length) 266{ 267 acpi_status status; 268 269 270 FUNCTION_TRACE_PTR ("Ex_access_buffer_field", obj_desc); 271 272 273 /* 274 * If the Buffer_field arguments have not been previously evaluated, 275 * evaluate them now and save the results. 276 */ 277 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 278 status = acpi_ds_get_buffer_field_arguments (obj_desc); 279 if (ACPI_FAILURE (status)) { 280 return_ACPI_STATUS (status); 281 } 282 } 283 284 285 status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); 286 287 return_ACPI_STATUS (status); 288} 289 290 291/******************************************************************************* 292 * 293 * FUNCTION: Acpi_ex_access_region_field 294 * 295 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 296 * *Field_node - Parent node for field to be accessed 297 * *Buffer - Value(s) to be read or written 298 * Buffer_length - Number of bytes to transfer 299 * 300 * RETURN: Status 301 * 302 * DESCRIPTION: Read or write a named field 303 * 304 ******************************************************************************/ 305 306acpi_status 307acpi_ex_access_region_field ( 308 u32 mode, 309 acpi_operand_object *obj_desc, 310 void *buffer, 311 u32 buffer_length) 312{ 313 acpi_status status; 314 u8 locked; 315 316 317 FUNCTION_TRACE_PTR ("Ex_access_region_field", obj_desc); 318 319 320 /* 321 * Get the global lock if needed 322 */ 323 locked = acpi_ex_acquire_global_lock (obj_desc->field.lock_rule); 324 325 status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); 326 327 328 /* 329 * Release global lock if we acquired it earlier 330 */ 331 acpi_ex_release_global_lock (locked); 332 333 return_ACPI_STATUS (status); 334} 335 336 337/******************************************************************************* 338 * 339 * FUNCTION: Acpi_ex_access_bank_field 340 * 341 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 342 * *Field_node - Parent node for field to be accessed 343 * *Buffer - Value(s) to be read or written 344 * Buffer_length - Number of bytes to transfer 345 * 346 * RETURN: Status 347 * 348 * DESCRIPTION: Read or write a Bank Field 349 * 350 ******************************************************************************/ 351 352acpi_status 353acpi_ex_access_bank_field ( 354 u32 mode, 355 acpi_operand_object *obj_desc, 356 void *buffer, 357 u32 buffer_length) 358{ 359 acpi_status status; 360 u8 locked; 361 362 363 FUNCTION_TRACE_PTR ("Ex_access_bank_field", obj_desc); 364 365 366 /* 367 * Get the global lock if needed 368 */ 369 locked = acpi_ex_acquire_global_lock (obj_desc->bank_field.lock_rule); 370 371 372 /* 373 * Write the Bank_value to the Bank_register to select the bank. 374 * The Bank_value for this Bank_field is specified in the 375 * Bank_field ASL declaration. The Bank_register is always a Field in 376 * an operation region. 377 */ 378 status = acpi_ex_common_access_field (ACPI_WRITE, 379 obj_desc->bank_field.bank_register_obj, 380 &obj_desc->bank_field.value, 381 sizeof (obj_desc->bank_field.value)); 382 if (ACPI_FAILURE (status)) { 383 goto cleanup; 384 } 385 386 /* 387 * The bank was successfully selected, now read or write the actual 388 * data. 389 */ 390 status = acpi_ex_common_access_field (mode, obj_desc, buffer, buffer_length); 391 392 393cleanup: 394 /* 395 * Release global lock if we acquired it earlier 396 */ 397 acpi_ex_release_global_lock (locked); 398 399 return_ACPI_STATUS (status); 400} 401 402 403/******************************************************************************* 404 * 405 * FUNCTION: Acpi_ex_access_index_field 406 * 407 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 408 * *Field_node - Parent node for field to be accessed 409 * *Buffer - Value(s) to be read or written 410 * Buffer_length - Number of bytes to transfer 411 * 412 * RETURN: Status 413 * 414 * DESCRIPTION: Read or write a Index Field 415 * 416 ******************************************************************************/ 417 418acpi_status 419acpi_ex_access_index_field ( 420 u32 mode, 421 acpi_operand_object *obj_desc, 422 void *buffer, 423 u32 buffer_length) 424{ 425 acpi_status status; 426 u8 locked; 427 428 429 FUNCTION_TRACE_PTR ("Ex_access_index_field", obj_desc); 430 431 432 /* 433 * Get the global lock if needed 434 */ 435 locked = acpi_ex_acquire_global_lock (obj_desc->index_field.lock_rule); 436 437 438 /* 439 * Set Index value to select proper Data register 440 */ 441 status = acpi_ex_common_access_field (ACPI_WRITE, 442 obj_desc->index_field.index_obj, 443 &obj_desc->index_field.value, 444 sizeof (obj_desc->index_field.value)); 445 if (ACPI_FAILURE (status)) { 446 goto cleanup; 447 } 448 449 /* Now read/write the data register */ 450 451 status = acpi_ex_common_access_field (mode, obj_desc->index_field.data_obj, 452 buffer, buffer_length); 453 454cleanup: 455 /* 456 * Release global lock if we acquired it earlier 457 */ 458 acpi_ex_release_global_lock (locked); 459 460 return_ACPI_STATUS (status); 461} 462 463 464/******************************************************************************* 465 * 466 * FUNCTION: Acpi_ex_common_access_field 467 * 468 * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE 469 * *Field_node - Parent node for field to be accessed 470 * *Buffer - Value(s) to be read or written 471 * Buffer_length - Size of buffer, in bytes. Must be large 472 * enough for all bits of the field. 473 * 474 * RETURN: Status 475 * 476 * DESCRIPTION: Read or write a named field 477 * 478 ******************************************************************************/ 479 480acpi_status 481acpi_ex_common_access_field ( 482 u32 mode, 483 acpi_operand_object *obj_desc, 484 void *buffer, 485 u32 buffer_length) 486{ 487 acpi_status status; 488 489 490 FUNCTION_TRACE_PTR ("Ex_common_access_field", obj_desc); 491 492 493 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj=%p Type=%X Buf=%p Len=%X\n", 494 obj_desc, obj_desc->common.type, buffer, buffer_length)); 495 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode=%d Bit_len=%X Bit_off=%X Byte_off=%X\n", 496 mode, obj_desc->common_field.bit_length, 497 obj_desc->common_field.start_field_bit_offset, 498 obj_desc->common_field.base_byte_offset)); 499 500 501 /* Perform the actual read or write of the field */ 502 503 switch (mode) { 504 case ACPI_READ: 505 506 status = acpi_ex_extract_from_field (obj_desc, buffer, buffer_length); 507 break; 508 509 510 case ACPI_WRITE: 511 512 status = acpi_ex_insert_into_field (obj_desc, buffer, buffer_length); 513 break; 514 515 516 default: 517 518 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown I/O Mode: %X\n", mode)); 519 status = AE_BAD_PARAMETER; 520 break; 521 } 522 523 524 return_ACPI_STATUS (status); 525} 526 527