diff options
Diffstat (limited to 'drivers/acpi/executer/exfldio.c')
-rw-r--r-- | drivers/acpi/executer/exfldio.c | 133 |
1 files changed, 87 insertions, 46 deletions
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 9d0f9d2e9061..3c2f89e00f78 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c | |||
@@ -52,12 +52,31 @@ | |||
52 | #define _COMPONENT ACPI_EXECUTER | 52 | #define _COMPONENT ACPI_EXECUTER |
53 | ACPI_MODULE_NAME ("exfldio") | 53 | ACPI_MODULE_NAME ("exfldio") |
54 | 54 | ||
55 | /* Local prototypes */ | ||
56 | |||
57 | static acpi_status | ||
58 | acpi_ex_field_datum_io ( | ||
59 | union acpi_operand_object *obj_desc, | ||
60 | u32 field_datum_byte_offset, | ||
61 | acpi_integer *value, | ||
62 | u32 read_write); | ||
63 | |||
64 | static u8 | ||
65 | acpi_ex_register_overflow ( | ||
66 | union acpi_operand_object *obj_desc, | ||
67 | acpi_integer value); | ||
68 | |||
69 | static acpi_status | ||
70 | acpi_ex_setup_region ( | ||
71 | union acpi_operand_object *obj_desc, | ||
72 | u32 field_datum_byte_offset); | ||
73 | |||
55 | 74 | ||
56 | /******************************************************************************* | 75 | /******************************************************************************* |
57 | * | 76 | * |
58 | * FUNCTION: acpi_ex_setup_region | 77 | * FUNCTION: acpi_ex_setup_region |
59 | * | 78 | * |
60 | * PARAMETERS: *obj_desc - Field to be read or written | 79 | * PARAMETERS: obj_desc - Field to be read or written |
61 | * field_datum_byte_offset - Byte offset of this datum within the | 80 | * field_datum_byte_offset - Byte offset of this datum within the |
62 | * parent field | 81 | * parent field |
63 | * | 82 | * |
@@ -69,7 +88,7 @@ | |||
69 | * | 88 | * |
70 | ******************************************************************************/ | 89 | ******************************************************************************/ |
71 | 90 | ||
72 | acpi_status | 91 | static acpi_status |
73 | acpi_ex_setup_region ( | 92 | acpi_ex_setup_region ( |
74 | union acpi_operand_object *obj_desc, | 93 | union acpi_operand_object *obj_desc, |
75 | u32 field_datum_byte_offset) | 94 | u32 field_datum_byte_offset) |
@@ -127,9 +146,9 @@ acpi_ex_setup_region ( | |||
127 | * length of one field datum (access width) must fit within the region. | 146 | * length of one field datum (access width) must fit within the region. |
128 | * (Region length is specified in bytes) | 147 | * (Region length is specified in bytes) |
129 | */ | 148 | */ |
130 | if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset | 149 | if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + |
131 | + field_datum_byte_offset | 150 | field_datum_byte_offset + |
132 | + obj_desc->common_field.access_byte_width)) { | 151 | obj_desc->common_field.access_byte_width)) { |
133 | if (acpi_gbl_enable_interpreter_slack) { | 152 | if (acpi_gbl_enable_interpreter_slack) { |
134 | /* | 153 | /* |
135 | * Slack mode only: We will go ahead and allow access to this | 154 | * Slack mode only: We will go ahead and allow access to this |
@@ -155,7 +174,8 @@ acpi_ex_setup_region ( | |||
155 | "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", | 174 | "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", |
156 | acpi_ut_get_node_name (obj_desc->common_field.node), | 175 | acpi_ut_get_node_name (obj_desc->common_field.node), |
157 | obj_desc->common_field.access_byte_width, | 176 | obj_desc->common_field.access_byte_width, |
158 | acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); | 177 | acpi_ut_get_node_name (rgn_desc->region.node), |
178 | rgn_desc->region.length)); | ||
159 | } | 179 | } |
160 | 180 | ||
161 | /* | 181 | /* |
@@ -167,7 +187,8 @@ acpi_ex_setup_region ( | |||
167 | acpi_ut_get_node_name (obj_desc->common_field.node), | 187 | acpi_ut_get_node_name (obj_desc->common_field.node), |
168 | obj_desc->common_field.base_byte_offset, | 188 | obj_desc->common_field.base_byte_offset, |
169 | field_datum_byte_offset, obj_desc->common_field.access_byte_width, | 189 | field_datum_byte_offset, obj_desc->common_field.access_byte_width, |
170 | acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); | 190 | acpi_ut_get_node_name (rgn_desc->region.node), |
191 | rgn_desc->region.length)); | ||
171 | 192 | ||
172 | return_ACPI_STATUS (AE_AML_REGION_LIMIT); | 193 | return_ACPI_STATUS (AE_AML_REGION_LIMIT); |
173 | } | 194 | } |
@@ -180,10 +201,10 @@ acpi_ex_setup_region ( | |||
180 | * | 201 | * |
181 | * FUNCTION: acpi_ex_access_region | 202 | * FUNCTION: acpi_ex_access_region |
182 | * | 203 | * |
183 | * PARAMETERS: *obj_desc - Field to be read | 204 | * PARAMETERS: obj_desc - Field to be read |
184 | * field_datum_byte_offset - Byte offset of this datum within the | 205 | * field_datum_byte_offset - Byte offset of this datum within the |
185 | * parent field | 206 | * parent field |
186 | * *Value - Where to store value (must at least | 207 | * Value - Where to store value (must at least |
187 | * the size of acpi_integer) | 208 | * the size of acpi_integer) |
188 | * Function - Read or Write flag plus other region- | 209 | * Function - Read or Write flag plus other region- |
189 | * dependent flags | 210 | * dependent flags |
@@ -226,9 +247,9 @@ acpi_ex_access_region ( | |||
226 | * 3) The current offset into the field | 247 | * 3) The current offset into the field |
227 | */ | 248 | */ |
228 | rgn_desc = obj_desc->common_field.region_obj; | 249 | rgn_desc = obj_desc->common_field.region_obj; |
229 | address = rgn_desc->region.address | 250 | address = rgn_desc->region.address + |
230 | + obj_desc->common_field.base_byte_offset | 251 | obj_desc->common_field.base_byte_offset + |
231 | + field_datum_byte_offset; | 252 | field_datum_byte_offset; |
232 | 253 | ||
233 | if ((function & ACPI_IO_MASK) == ACPI_READ) { | 254 | if ((function & ACPI_IO_MASK) == ACPI_READ) { |
234 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); | 255 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); |
@@ -249,7 +270,8 @@ acpi_ex_access_region ( | |||
249 | /* Invoke the appropriate address_space/op_region handler */ | 270 | /* Invoke the appropriate address_space/op_region handler */ |
250 | 271 | ||
251 | status = acpi_ev_address_space_dispatch (rgn_desc, function, | 272 | status = acpi_ev_address_space_dispatch (rgn_desc, function, |
252 | address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value); | 273 | address, |
274 | ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value); | ||
253 | 275 | ||
254 | if (ACPI_FAILURE (status)) { | 276 | if (ACPI_FAILURE (status)) { |
255 | if (status == AE_NOT_IMPLEMENTED) { | 277 | if (status == AE_NOT_IMPLEMENTED) { |
@@ -274,7 +296,7 @@ acpi_ex_access_region ( | |||
274 | * | 296 | * |
275 | * FUNCTION: acpi_ex_register_overflow | 297 | * FUNCTION: acpi_ex_register_overflow |
276 | * | 298 | * |
277 | * PARAMETERS: *obj_desc - Register(Field) to be written | 299 | * PARAMETERS: obj_desc - Register(Field) to be written |
278 | * Value - Value to be stored | 300 | * Value - Value to be stored |
279 | * | 301 | * |
280 | * RETURN: TRUE if value overflows the field, FALSE otherwise | 302 | * RETURN: TRUE if value overflows the field, FALSE otherwise |
@@ -287,7 +309,7 @@ acpi_ex_access_region ( | |||
287 | * | 309 | * |
288 | ******************************************************************************/ | 310 | ******************************************************************************/ |
289 | 311 | ||
290 | u8 | 312 | static u8 |
291 | acpi_ex_register_overflow ( | 313 | acpi_ex_register_overflow ( |
292 | union acpi_operand_object *obj_desc, | 314 | union acpi_operand_object *obj_desc, |
293 | acpi_integer value) | 315 | acpi_integer value) |
@@ -319,10 +341,10 @@ acpi_ex_register_overflow ( | |||
319 | * | 341 | * |
320 | * FUNCTION: acpi_ex_field_datum_io | 342 | * FUNCTION: acpi_ex_field_datum_io |
321 | * | 343 | * |
322 | * PARAMETERS: *obj_desc - Field to be read | 344 | * PARAMETERS: obj_desc - Field to be read |
323 | * field_datum_byte_offset - Byte offset of this datum within the | 345 | * field_datum_byte_offset - Byte offset of this datum within the |
324 | * parent field | 346 | * parent field |
325 | * *Value - Where to store value (must be 64 bits) | 347 | * Value - Where to store value (must be 64 bits) |
326 | * read_write - Read or Write flag | 348 | * read_write - Read or Write flag |
327 | * | 349 | * |
328 | * RETURN: Status | 350 | * RETURN: Status |
@@ -333,7 +355,7 @@ acpi_ex_register_overflow ( | |||
333 | * | 355 | * |
334 | ******************************************************************************/ | 356 | ******************************************************************************/ |
335 | 357 | ||
336 | acpi_status | 358 | static acpi_status |
337 | acpi_ex_field_datum_io ( | 359 | acpi_ex_field_datum_io ( |
338 | union acpi_operand_object *obj_desc, | 360 | union acpi_operand_object *obj_desc, |
339 | u32 field_datum_byte_offset, | 361 | u32 field_datum_byte_offset, |
@@ -350,7 +372,9 @@ acpi_ex_field_datum_io ( | |||
350 | if (read_write == ACPI_READ) { | 372 | if (read_write == ACPI_READ) { |
351 | if (!value) { | 373 | if (!value) { |
352 | local_value = 0; | 374 | local_value = 0; |
353 | value = &local_value; /* To support reads without saving return value */ | 375 | |
376 | /* To support reads without saving return value */ | ||
377 | value = &local_value; | ||
354 | } | 378 | } |
355 | 379 | ||
356 | /* Clear the entire return buffer first, [Very Important!] */ | 380 | /* Clear the entire return buffer first, [Very Important!] */ |
@@ -363,8 +387,10 @@ acpi_ex_field_datum_io ( | |||
363 | * | 387 | * |
364 | * buffer_field - Read/write from/to a Buffer | 388 | * buffer_field - Read/write from/to a Buffer |
365 | * region_field - Read/write from/to a Operation Region. | 389 | * region_field - Read/write from/to a Operation Region. |
366 | * bank_field - Write to a Bank Register, then read/write from/to an op_region | 390 | * bank_field - Write to a Bank Register, then read/write from/to an |
367 | * index_field - Write to an Index Register, then read/write from/to a Data Register | 391 | * operation_region |
392 | * index_field - Write to an Index Register, then read/write from/to a | ||
393 | * Data Register | ||
368 | */ | 394 | */ |
369 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { | 395 | switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { |
370 | case ACPI_TYPE_BUFFER_FIELD: | 396 | case ACPI_TYPE_BUFFER_FIELD: |
@@ -384,19 +410,20 @@ acpi_ex_field_datum_io ( | |||
384 | * Copy the data from the source buffer. | 410 | * Copy the data from the source buffer. |
385 | * Length is the field width in bytes. | 411 | * Length is the field width in bytes. |
386 | */ | 412 | */ |
387 | ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer | 413 | ACPI_MEMCPY (value, |
388 | + obj_desc->buffer_field.base_byte_offset | 414 | (obj_desc->buffer_field.buffer_obj)->buffer.pointer + |
389 | + field_datum_byte_offset, | 415 | obj_desc->buffer_field.base_byte_offset + |
390 | obj_desc->common_field.access_byte_width); | 416 | field_datum_byte_offset, |
417 | obj_desc->common_field.access_byte_width); | ||
391 | } | 418 | } |
392 | else { | 419 | else { |
393 | /* | 420 | /* |
394 | * Copy the data to the target buffer. | 421 | * Copy the data to the target buffer. |
395 | * Length is the field width in bytes. | 422 | * Length is the field width in bytes. |
396 | */ | 423 | */ |
397 | ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer | 424 | ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer + |
398 | + obj_desc->buffer_field.base_byte_offset | 425 | obj_desc->buffer_field.base_byte_offset + |
399 | + field_datum_byte_offset, | 426 | field_datum_byte_offset, |
400 | value, obj_desc->common_field.access_byte_width); | 427 | value, obj_desc->common_field.access_byte_width); |
401 | } | 428 | } |
402 | 429 | ||
@@ -406,8 +433,10 @@ acpi_ex_field_datum_io ( | |||
406 | 433 | ||
407 | case ACPI_TYPE_LOCAL_BANK_FIELD: | 434 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
408 | 435 | ||
409 | /* Ensure that the bank_value is not beyond the capacity of the register */ | 436 | /* |
410 | 437 | * Ensure that the bank_value is not beyond the capacity of | |
438 | * the register | ||
439 | */ | ||
411 | if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj, | 440 | if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj, |
412 | (acpi_integer) obj_desc->bank_field.value)) { | 441 | (acpi_integer) obj_desc->bank_field.value)) { |
413 | return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); | 442 | return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); |
@@ -445,8 +474,10 @@ acpi_ex_field_datum_io ( | |||
445 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | 474 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
446 | 475 | ||
447 | 476 | ||
448 | /* Ensure that the index_value is not beyond the capacity of the register */ | 477 | /* |
449 | 478 | * Ensure that the index_value is not beyond the capacity of | |
479 | * the register | ||
480 | */ | ||
450 | if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, | 481 | if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, |
451 | (acpi_integer) obj_desc->index_field.value)) { | 482 | (acpi_integer) obj_desc->index_field.value)) { |
452 | return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); | 483 | return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); |
@@ -496,14 +527,16 @@ acpi_ex_field_datum_io ( | |||
496 | 527 | ||
497 | if (ACPI_SUCCESS (status)) { | 528 | if (ACPI_SUCCESS (status)) { |
498 | if (read_write == ACPI_READ) { | 529 | if (read_write == ACPI_READ) { |
499 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n", | 530 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
500 | ACPI_FORMAT_UINT64 (*value), | 531 | "Value Read %8.8X%8.8X, Width %d\n", |
501 | obj_desc->common_field.access_byte_width)); | 532 | ACPI_FORMAT_UINT64 (*value), |
533 | obj_desc->common_field.access_byte_width)); | ||
502 | } | 534 | } |
503 | else { | 535 | else { |
504 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", | 536 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
505 | ACPI_FORMAT_UINT64 (*value), | 537 | "Value Written %8.8X%8.8X, Width %d\n", |
506 | obj_desc->common_field.access_byte_width)); | 538 | ACPI_FORMAT_UINT64 (*value), |
539 | obj_desc->common_field.access_byte_width)); | ||
507 | } | 540 | } |
508 | } | 541 | } |
509 | 542 | ||
@@ -515,8 +548,10 @@ acpi_ex_field_datum_io ( | |||
515 | * | 548 | * |
516 | * FUNCTION: acpi_ex_write_with_update_rule | 549 | * FUNCTION: acpi_ex_write_with_update_rule |
517 | * | 550 | * |
518 | * PARAMETERS: *obj_desc - Field to be set | 551 | * PARAMETERS: obj_desc - Field to be written |
519 | * Value - Value to store | 552 | * Mask - bitmask within field datum |
553 | * field_value - Value to write | ||
554 | * field_datum_byte_offset - Offset of datum within field | ||
520 | * | 555 | * |
521 | * RETURN: Status | 556 | * RETURN: Status |
522 | * | 557 | * |
@@ -689,7 +724,8 @@ acpi_ex_extract_from_field ( | |||
689 | /* Merge with previous datum if necessary */ | 724 | /* Merge with previous datum if necessary */ |
690 | 725 | ||
691 | merged_datum |= raw_datum << | 726 | merged_datum |= raw_datum << |
692 | (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset); | 727 | (obj_desc->common_field.access_bit_width - |
728 | obj_desc->common_field.start_field_bit_offset); | ||
693 | 729 | ||
694 | if (i == datum_count) { | 730 | if (i == datum_count) { |
695 | break; | 731 | break; |
@@ -707,7 +743,8 @@ acpi_ex_extract_from_field ( | |||
707 | 743 | ||
708 | /* Mask off any extra bits in the last datum */ | 744 | /* Mask off any extra bits in the last datum */ |
709 | 745 | ||
710 | buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width; | 746 | buffer_tail_bits = obj_desc->common_field.bit_length % |
747 | obj_desc->common_field.access_bit_width; | ||
711 | if (buffer_tail_bits) { | 748 | if (buffer_tail_bits) { |
712 | merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits); | 749 | merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits); |
713 | } | 750 | } |
@@ -791,7 +828,8 @@ acpi_ex_insert_into_field ( | |||
791 | /* Write merged datum to the target field */ | 828 | /* Write merged datum to the target field */ |
792 | 829 | ||
793 | merged_datum &= mask; | 830 | merged_datum &= mask; |
794 | status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset); | 831 | status = acpi_ex_write_with_update_rule (obj_desc, mask, |
832 | merged_datum, field_offset); | ||
795 | if (ACPI_FAILURE (status)) { | 833 | if (ACPI_FAILURE (status)) { |
796 | return_ACPI_STATUS (status); | 834 | return_ACPI_STATUS (status); |
797 | } | 835 | } |
@@ -800,7 +838,8 @@ acpi_ex_insert_into_field ( | |||
800 | 838 | ||
801 | field_offset += obj_desc->common_field.access_byte_width; | 839 | field_offset += obj_desc->common_field.access_byte_width; |
802 | merged_datum = raw_datum >> | 840 | merged_datum = raw_datum >> |
803 | (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset); | 841 | (obj_desc->common_field.access_bit_width - |
842 | obj_desc->common_field.start_field_bit_offset); | ||
804 | mask = ACPI_INTEGER_MAX; | 843 | mask = ACPI_INTEGER_MAX; |
805 | 844 | ||
806 | if (i == datum_count) { | 845 | if (i == datum_count) { |
@@ -819,7 +858,8 @@ acpi_ex_insert_into_field ( | |||
819 | /* Mask off any extra bits in the last datum */ | 858 | /* Mask off any extra bits in the last datum */ |
820 | 859 | ||
821 | buffer_tail_bits = (obj_desc->common_field.bit_length + | 860 | buffer_tail_bits = (obj_desc->common_field.bit_length + |
822 | obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width; | 861 | obj_desc->common_field.start_field_bit_offset) % |
862 | obj_desc->common_field.access_bit_width; | ||
823 | if (buffer_tail_bits) { | 863 | if (buffer_tail_bits) { |
824 | mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits); | 864 | mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits); |
825 | } | 865 | } |
@@ -827,7 +867,8 @@ acpi_ex_insert_into_field ( | |||
827 | /* Write the last datum to the field */ | 867 | /* Write the last datum to the field */ |
828 | 868 | ||
829 | merged_datum &= mask; | 869 | merged_datum &= mask; |
830 | status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset); | 870 | status = acpi_ex_write_with_update_rule (obj_desc, |
871 | mask, merged_datum, field_offset); | ||
831 | 872 | ||
832 | return_ACPI_STATUS (status); | 873 | return_ACPI_STATUS (status); |
833 | } | 874 | } |