9fe27fd04a2ff76286a94dffc97dadb525415a65
[safe/jmp/linux-2.6] / drivers / acpi / executer / exfldio.c
1 /******************************************************************************
2  *
3  * Module Name: exfldio - Aml Field I/O
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2006, 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/acinterp.h>
46 #include <acpi/amlcode.h>
47 #include <acpi/acevents.h>
48 #include <acpi/acdispat.h>
49
50 #define _COMPONENT          ACPI_EXECUTER
51 ACPI_MODULE_NAME("exfldio")
52
53 /* Local prototypes */
54 static acpi_status
55 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
56                        u32 field_datum_byte_offset,
57                        acpi_integer * value, u32 read_write);
58
59 static u8
60 acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
61                           acpi_integer value);
62
63 static acpi_status
64 acpi_ex_setup_region(union acpi_operand_object *obj_desc,
65                      u32 field_datum_byte_offset);
66
67 /*******************************************************************************
68  *
69  * FUNCTION:    acpi_ex_setup_region
70  *
71  * PARAMETERS:  obj_desc                - Field to be read or written
72  *              field_datum_byte_offset - Byte offset of this datum within the
73  *                                        parent field
74  *
75  * RETURN:      Status
76  *
77  * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
78  *              acpi_ex_insert_into_field. Initialize the Region if necessary and
79  *              validate the request.
80  *
81  ******************************************************************************/
82
83 static acpi_status
84 acpi_ex_setup_region(union acpi_operand_object *obj_desc,
85                      u32 field_datum_byte_offset)
86 {
87         acpi_status status = AE_OK;
88         union acpi_operand_object *rgn_desc;
89
90         ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset);
91
92         rgn_desc = obj_desc->common_field.region_obj;
93
94         /* We must have a valid region */
95
96         if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
97                 ACPI_REPORT_ERROR(("Needed Region, found type %X (%s)\n",
98                                    ACPI_GET_OBJECT_TYPE(rgn_desc),
99                                    acpi_ut_get_object_type_name(rgn_desc)));
100
101                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
102         }
103
104         /*
105          * If the Region Address and Length have not been previously evaluated,
106          * evaluate them now and save the results.
107          */
108         if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
109                 status = acpi_ds_get_region_arguments(rgn_desc);
110                 if (ACPI_FAILURE(status)) {
111                         return_ACPI_STATUS(status);
112                 }
113         }
114
115         if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
116                 /* SMBus has a non-linear address space */
117
118                 return_ACPI_STATUS(AE_OK);
119         }
120 #ifdef ACPI_UNDER_DEVELOPMENT
121         /*
122          * If the Field access is any_acc, we can now compute the optimal
123          * access (because we know know the length of the parent region)
124          */
125         if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
126                 if (ACPI_FAILURE(status)) {
127                         return_ACPI_STATUS(status);
128                 }
129         }
130 #endif
131
132         /*
133          * Validate the request.  The entire request from the byte offset for a
134          * length of one field datum (access width) must fit within the region.
135          * (Region length is specified in bytes)
136          */
137         if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset +
138                                        field_datum_byte_offset +
139                                        obj_desc->common_field.
140                                        access_byte_width)) {
141                 if (acpi_gbl_enable_interpreter_slack) {
142                         /*
143                          * Slack mode only:  We will go ahead and allow access to this
144                          * field if it is within the region length rounded up to the next
145                          * access width boundary.
146                          */
147                         if (ACPI_ROUND_UP(rgn_desc->region.length,
148                                           obj_desc->common_field.
149                                           access_byte_width) >=
150                             (obj_desc->common_field.base_byte_offset +
151                              (acpi_native_uint) obj_desc->common_field.
152                              access_byte_width + field_datum_byte_offset)) {
153                                 return_ACPI_STATUS(AE_OK);
154                         }
155                 }
156
157                 if (rgn_desc->region.length <
158                     obj_desc->common_field.access_byte_width) {
159                         /*
160                          * This is the case where the access_type (acc_word, etc.) is wider
161                          * than the region itself.  For example, a region of length one
162                          * byte, and a field with Dword access specified.
163                          */
164                         ACPI_REPORT_ERROR(("Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", acpi_ut_get_node_name(obj_desc->common_field.node), obj_desc->common_field.access_byte_width, acpi_ut_get_node_name(rgn_desc->region.node), rgn_desc->region.length));
165                 }
166
167                 /*
168                  * Offset rounded up to next multiple of field width
169                  * exceeds region length, indicate an error
170                  */
171                 ACPI_REPORT_ERROR(("Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", acpi_ut_get_node_name(obj_desc->common_field.node), obj_desc->common_field.base_byte_offset, field_datum_byte_offset, obj_desc->common_field.access_byte_width, acpi_ut_get_node_name(rgn_desc->region.node), rgn_desc->region.length));
172
173                 return_ACPI_STATUS(AE_AML_REGION_LIMIT);
174         }
175
176         return_ACPI_STATUS(AE_OK);
177 }
178
179 /*******************************************************************************
180  *
181  * FUNCTION:    acpi_ex_access_region
182  *
183  * PARAMETERS:  obj_desc                - Field to be read
184  *              field_datum_byte_offset - Byte offset of this datum within the
185  *                                        parent field
186  *              Value                   - Where to store value (must at least
187  *                                        the size of acpi_integer)
188  *              Function                - Read or Write flag plus other region-
189  *                                        dependent flags
190  *
191  * RETURN:      Status
192  *
193  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
194  *
195  ******************************************************************************/
196
197 acpi_status
198 acpi_ex_access_region(union acpi_operand_object *obj_desc,
199                       u32 field_datum_byte_offset,
200                       acpi_integer * value, u32 function)
201 {
202         acpi_status status;
203         union acpi_operand_object *rgn_desc;
204         acpi_physical_address address;
205
206         ACPI_FUNCTION_TRACE("ex_access_region");
207
208         /*
209          * Ensure that the region operands are fully evaluated and verify
210          * the validity of the request
211          */
212         status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
213         if (ACPI_FAILURE(status)) {
214                 return_ACPI_STATUS(status);
215         }
216
217         /*
218          * The physical address of this field datum is:
219          *
220          * 1) The base of the region, plus
221          * 2) The base offset of the field, plus
222          * 3) The current offset into the field
223          */
224         rgn_desc = obj_desc->common_field.region_obj;
225         address = rgn_desc->region.address +
226             obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
227
228         if ((function & ACPI_IO_MASK) == ACPI_READ) {
229                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
230         } else {
231                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
232         }
233
234         ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
235                               " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
236                               acpi_ut_get_region_name(rgn_desc->region.
237                                                       space_id),
238                               rgn_desc->region.space_id,
239                               obj_desc->common_field.access_byte_width,
240                               obj_desc->common_field.base_byte_offset,
241                               field_datum_byte_offset,
242                               ACPI_FORMAT_UINT64(address)));
243
244         /* Invoke the appropriate address_space/op_region handler */
245
246         status = acpi_ev_address_space_dispatch(rgn_desc, function,
247                                                 address,
248                                                 ACPI_MUL_8(obj_desc->
249                                                            common_field.
250                                                            access_byte_width),
251                                                 value);
252
253         if (ACPI_FAILURE(status)) {
254                 if (status == AE_NOT_IMPLEMENTED) {
255                         ACPI_REPORT_ERROR(("Region %s(%X) not implemented\n",
256                                            acpi_ut_get_region_name(rgn_desc->
257                                                                    region.
258                                                                    space_id),
259                                            rgn_desc->region.space_id));
260                 } else if (status == AE_NOT_EXIST) {
261                         ACPI_REPORT_ERROR(("Region %s(%X) has no handler\n",
262                                            acpi_ut_get_region_name(rgn_desc->
263                                                                    region.
264                                                                    space_id),
265                                            rgn_desc->region.space_id));
266                 }
267         }
268
269         return_ACPI_STATUS(status);
270 }
271
272 /*******************************************************************************
273  *
274  * FUNCTION:    acpi_ex_register_overflow
275  *
276  * PARAMETERS:  obj_desc                - Register(Field) to be written
277  *              Value                   - Value to be stored
278  *
279  * RETURN:      TRUE if value overflows the field, FALSE otherwise
280  *
281  * DESCRIPTION: Check if a value is out of range of the field being written.
282  *              Used to check if the values written to Index and Bank registers
283  *              are out of range.  Normally, the value is simply truncated
284  *              to fit the field, but this case is most likely a serious
285  *              coding error in the ASL.
286  *
287  ******************************************************************************/
288
289 static u8
290 acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
291                           acpi_integer value)
292 {
293
294         if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
295                 /*
296                  * The field is large enough to hold the maximum integer, so we can
297                  * never overflow it.
298                  */
299                 return (FALSE);
300         }
301
302         if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) {
303                 /*
304                  * The Value is larger than the maximum value that can fit into
305                  * the register.
306                  */
307                 return (TRUE);
308         }
309
310         /* The Value will fit into the field with no truncation */
311
312         return (FALSE);
313 }
314
315 /*******************************************************************************
316  *
317  * FUNCTION:    acpi_ex_field_datum_io
318  *
319  * PARAMETERS:  obj_desc                - Field to be read
320  *              field_datum_byte_offset - Byte offset of this datum within the
321  *                                        parent field
322  *              Value                   - Where to store value (must be 64 bits)
323  *              read_write              - Read or Write flag
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Read or Write a single datum of a field.  The field_type is
328  *              demultiplexed here to handle the different types of fields
329  *              (buffer_field, region_field, index_field, bank_field)
330  *
331  ******************************************************************************/
332
333 static acpi_status
334 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
335                        u32 field_datum_byte_offset,
336                        acpi_integer * value, u32 read_write)
337 {
338         acpi_status status;
339         acpi_integer local_value;
340
341         ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset);
342
343         if (read_write == ACPI_READ) {
344                 if (!value) {
345                         local_value = 0;
346
347                         /* To support reads without saving return value */
348                         value = &local_value;
349                 }
350
351                 /* Clear the entire return buffer first, [Very Important!] */
352
353                 *value = 0;
354         }
355
356         /*
357          * The four types of fields are:
358          *
359          * buffer_field - Read/write from/to a Buffer
360          * region_field - Read/write from/to a Operation Region.
361          * bank_field  - Write to a Bank Register, then read/write from/to an
362          *               operation_region
363          * index_field - Write to an Index Register, then read/write from/to a
364          *               Data Register
365          */
366         switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
367         case ACPI_TYPE_BUFFER_FIELD:
368                 /*
369                  * If the buffer_field arguments have not been previously evaluated,
370                  * evaluate them now and save the results.
371                  */
372                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
373                         status = acpi_ds_get_buffer_field_arguments(obj_desc);
374                         if (ACPI_FAILURE(status)) {
375                                 return_ACPI_STATUS(status);
376                         }
377                 }
378
379                 if (read_write == ACPI_READ) {
380                         /*
381                          * Copy the data from the source buffer.
382                          * Length is the field width in bytes.
383                          */
384                         ACPI_MEMCPY(value,
385                                     (obj_desc->buffer_field.buffer_obj)->buffer.
386                                     pointer +
387                                     obj_desc->buffer_field.base_byte_offset +
388                                     field_datum_byte_offset,
389                                     obj_desc->common_field.access_byte_width);
390                 } else {
391                         /*
392                          * Copy the data to the target buffer.
393                          * Length is the field width in bytes.
394                          */
395                         ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
396                                     pointer +
397                                     obj_desc->buffer_field.base_byte_offset +
398                                     field_datum_byte_offset, value,
399                                     obj_desc->common_field.access_byte_width);
400                 }
401
402                 status = AE_OK;
403                 break;
404
405         case ACPI_TYPE_LOCAL_BANK_FIELD:
406
407                 /*
408                  * Ensure that the bank_value is not beyond the capacity of
409                  * the register
410                  */
411                 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
412                                               (acpi_integer) obj_desc->
413                                               bank_field.value)) {
414                         return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
415                 }
416
417                 /*
418                  * For bank_fields, we must write the bank_value to the bank_register
419                  * (itself a region_field) before we can access the data.
420                  */
421                 status =
422                     acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
423                                               &obj_desc->bank_field.value,
424                                               sizeof(obj_desc->bank_field.
425                                                      value));
426                 if (ACPI_FAILURE(status)) {
427                         return_ACPI_STATUS(status);
428                 }
429
430                 /*
431                  * Now that the Bank has been selected, fall through to the
432                  * region_field case and write the datum to the Operation Region
433                  */
434
435                 /*lint -fallthrough */
436
437         case ACPI_TYPE_LOCAL_REGION_FIELD:
438                 /*
439                  * For simple region_fields, we just directly access the owning
440                  * Operation Region.
441                  */
442                 status =
443                     acpi_ex_access_region(obj_desc, field_datum_byte_offset,
444                                           value, read_write);
445                 break;
446
447         case ACPI_TYPE_LOCAL_INDEX_FIELD:
448
449                 /*
450                  * Ensure that the index_value is not beyond the capacity of
451                  * the register
452                  */
453                 if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
454                                               (acpi_integer) obj_desc->
455                                               index_field.value)) {
456                         return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
457                 }
458
459                 /* Write the index value to the index_register (itself a region_field) */
460
461                 field_datum_byte_offset += obj_desc->index_field.value;
462
463                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
464                                   "Write to Index Register: Value %8.8X\n",
465                                   field_datum_byte_offset));
466
467                 status =
468                     acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
469                                               &field_datum_byte_offset,
470                                               sizeof(field_datum_byte_offset));
471                 if (ACPI_FAILURE(status)) {
472                         return_ACPI_STATUS(status);
473                 }
474
475                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
476                                   "I/O to Data Register: value_ptr %p\n",
477                                   value));
478
479                 if (read_write == ACPI_READ) {
480                         /* Read the datum from the data_register */
481
482                         status =
483                             acpi_ex_extract_from_field(obj_desc->index_field.
484                                                        data_obj, value,
485                                                        sizeof(acpi_integer));
486                 } else {
487                         /* Write the datum to the data_register */
488
489                         status =
490                             acpi_ex_insert_into_field(obj_desc->index_field.
491                                                       data_obj, value,
492                                                       sizeof(acpi_integer));
493                 }
494                 break;
495
496         default:
497
498                 ACPI_REPORT_ERROR(("Wrong object type in field I/O %X\n",
499                                    ACPI_GET_OBJECT_TYPE(obj_desc)));
500                 status = AE_AML_INTERNAL;
501                 break;
502         }
503
504         if (ACPI_SUCCESS(status)) {
505                 if (read_write == ACPI_READ) {
506                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
507                                           "Value Read %8.8X%8.8X, Width %d\n",
508                                           ACPI_FORMAT_UINT64(*value),
509                                           obj_desc->common_field.
510                                           access_byte_width));
511                 } else {
512                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
513                                           "Value Written %8.8X%8.8X, Width %d\n",
514                                           ACPI_FORMAT_UINT64(*value),
515                                           obj_desc->common_field.
516                                           access_byte_width));
517                 }
518         }
519
520         return_ACPI_STATUS(status);
521 }
522
523 /*******************************************************************************
524  *
525  * FUNCTION:    acpi_ex_write_with_update_rule
526  *
527  * PARAMETERS:  obj_desc                - Field to be written
528  *              Mask                    - bitmask within field datum
529  *              field_value             - Value to write
530  *              field_datum_byte_offset - Offset of datum within field
531  *
532  * RETURN:      Status
533  *
534  * DESCRIPTION: Apply the field update rule to a field write
535  *
536  ******************************************************************************/
537
538 acpi_status
539 acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
540                                acpi_integer mask,
541                                acpi_integer field_value,
542                                u32 field_datum_byte_offset)
543 {
544         acpi_status status = AE_OK;
545         acpi_integer merged_value;
546         acpi_integer current_value;
547
548         ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask);
549
550         /* Start with the new bits  */
551
552         merged_value = field_value;
553
554         /* If the mask is all ones, we don't need to worry about the update rule */
555
556         if (mask != ACPI_INTEGER_MAX) {
557                 /* Decode the update rule */
558
559                 switch (obj_desc->common_field.
560                         field_flags & AML_FIELD_UPDATE_RULE_MASK) {
561                 case AML_FIELD_UPDATE_PRESERVE:
562                         /*
563                          * Check if update rule needs to be applied (not if mask is all
564                          * ones)  The left shift drops the bits we want to ignore.
565                          */
566                         if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
567                                        ACPI_MUL_8(obj_desc->common_field.
568                                                   access_byte_width))) != 0) {
569                                 /*
570                                  * Read the current contents of the byte/word/dword containing
571                                  * the field, and merge with the new field value.
572                                  */
573                                 status =
574                                     acpi_ex_field_datum_io(obj_desc,
575                                                            field_datum_byte_offset,
576                                                            &current_value,
577                                                            ACPI_READ);
578                                 if (ACPI_FAILURE(status)) {
579                                         return_ACPI_STATUS(status);
580                                 }
581
582                                 merged_value |= (current_value & ~mask);
583                         }
584                         break;
585
586                 case AML_FIELD_UPDATE_WRITE_AS_ONES:
587
588                         /* Set positions outside the field to all ones */
589
590                         merged_value |= ~mask;
591                         break;
592
593                 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
594
595                         /* Set positions outside the field to all zeros */
596
597                         merged_value &= mask;
598                         break;
599
600                 default:
601
602                         ACPI_REPORT_ERROR(("Unknown update_rule value: %X\n",
603                                            (obj_desc->common_field.
604                                             field_flags &
605                                             AML_FIELD_UPDATE_RULE_MASK)));
606                         return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
607                 }
608         }
609
610         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
611                           "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
612                           ACPI_FORMAT_UINT64(mask),
613                           field_datum_byte_offset,
614                           obj_desc->common_field.access_byte_width,
615                           ACPI_FORMAT_UINT64(field_value),
616                           ACPI_FORMAT_UINT64(merged_value)));
617
618         /* Write the merged value */
619
620         status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
621                                         &merged_value, ACPI_WRITE);
622
623         return_ACPI_STATUS(status);
624 }
625
626 /*******************************************************************************
627  *
628  * FUNCTION:    acpi_ex_extract_from_field
629  *
630  * PARAMETERS:  obj_desc            - Field to be read
631  *              Buffer              - Where to store the field data
632  *              buffer_length       - Length of Buffer
633  *
634  * RETURN:      Status
635  *
636  * DESCRIPTION: Retrieve the current value of the given field
637  *
638  ******************************************************************************/
639
640 acpi_status
641 acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
642                            void *buffer, u32 buffer_length)
643 {
644         acpi_status status;
645         acpi_integer raw_datum;
646         acpi_integer merged_datum;
647         u32 field_offset = 0;
648         u32 buffer_offset = 0;
649         u32 buffer_tail_bits;
650         u32 datum_count;
651         u32 field_datum_count;
652         u32 i;
653
654         ACPI_FUNCTION_TRACE("ex_extract_from_field");
655
656         /* Validate target buffer and clear it */
657
658         if (buffer_length <
659             ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
660                 ACPI_REPORT_ERROR(("Field size %X (bits) is too large for buffer (%X)\n", obj_desc->common_field.bit_length, buffer_length));
661
662                 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
663         }
664         ACPI_MEMSET(buffer, 0, buffer_length);
665
666         /* Compute the number of datums (access width data items) */
667
668         datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
669                                        obj_desc->common_field.access_bit_width);
670         field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
671                                              obj_desc->common_field.
672                                              start_field_bit_offset,
673                                              obj_desc->common_field.
674                                              access_bit_width);
675
676         /* Priming read from the field */
677
678         status =
679             acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
680                                    ACPI_READ);
681         if (ACPI_FAILURE(status)) {
682                 return_ACPI_STATUS(status);
683         }
684         merged_datum =
685             raw_datum >> obj_desc->common_field.start_field_bit_offset;
686
687         /* Read the rest of the field */
688
689         for (i = 1; i < field_datum_count; i++) {
690                 /* Get next input datum from the field */
691
692                 field_offset += obj_desc->common_field.access_byte_width;
693                 status = acpi_ex_field_datum_io(obj_desc, field_offset,
694                                                 &raw_datum, ACPI_READ);
695                 if (ACPI_FAILURE(status)) {
696                         return_ACPI_STATUS(status);
697                 }
698
699                 /* Merge with previous datum if necessary */
700
701                 merged_datum |= raw_datum <<
702                     (obj_desc->common_field.access_bit_width -
703                      obj_desc->common_field.start_field_bit_offset);
704
705                 if (i == datum_count) {
706                         break;
707                 }
708
709                 /* Write merged datum to target buffer */
710
711                 ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
712                             ACPI_MIN(obj_desc->common_field.access_byte_width,
713                                      buffer_length - buffer_offset));
714
715                 buffer_offset += obj_desc->common_field.access_byte_width;
716                 merged_datum =
717                     raw_datum >> obj_desc->common_field.start_field_bit_offset;
718         }
719
720         /* Mask off any extra bits in the last datum */
721
722         buffer_tail_bits = obj_desc->common_field.bit_length %
723             obj_desc->common_field.access_bit_width;
724         if (buffer_tail_bits) {
725                 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
726         }
727
728         /* Write the last datum to the buffer */
729
730         ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
731                     ACPI_MIN(obj_desc->common_field.access_byte_width,
732                              buffer_length - buffer_offset));
733
734         return_ACPI_STATUS(AE_OK);
735 }
736
737 /*******************************************************************************
738  *
739  * FUNCTION:    acpi_ex_insert_into_field
740  *
741  * PARAMETERS:  obj_desc            - Field to be written
742  *              Buffer              - Data to be written
743  *              buffer_length       - Length of Buffer
744  *
745  * RETURN:      Status
746  *
747  * DESCRIPTION: Store the Buffer contents into the given field
748  *
749  ******************************************************************************/
750
751 acpi_status
752 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
753                           void *buffer, u32 buffer_length)
754 {
755         acpi_status status;
756         acpi_integer mask;
757         acpi_integer merged_datum;
758         acpi_integer raw_datum = 0;
759         u32 field_offset = 0;
760         u32 buffer_offset = 0;
761         u32 buffer_tail_bits;
762         u32 datum_count;
763         u32 field_datum_count;
764         u32 i;
765
766         ACPI_FUNCTION_TRACE("ex_insert_into_field");
767
768         /* Validate input buffer */
769
770         if (buffer_length <
771             ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
772                 ACPI_REPORT_ERROR(("Field size %X (bits) is too large for buffer (%X)\n", obj_desc->common_field.bit_length, buffer_length));
773
774                 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
775         }
776
777         /* Compute the number of datums (access width data items) */
778
779         mask =
780             ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
781         datum_count =
782             ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
783                              obj_desc->common_field.access_bit_width);
784         field_datum_count =
785             ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
786                              obj_desc->common_field.start_field_bit_offset,
787                              obj_desc->common_field.access_bit_width);
788
789         /* Get initial Datum from the input buffer */
790
791         ACPI_MEMCPY(&raw_datum, buffer,
792                     ACPI_MIN(obj_desc->common_field.access_byte_width,
793                              buffer_length - buffer_offset));
794
795         merged_datum =
796             raw_datum << obj_desc->common_field.start_field_bit_offset;
797
798         /* Write the entire field */
799
800         for (i = 1; i < field_datum_count; i++) {
801                 /* Write merged datum to the target field */
802
803                 merged_datum &= mask;
804                 status = acpi_ex_write_with_update_rule(obj_desc, mask,
805                                                         merged_datum,
806                                                         field_offset);
807                 if (ACPI_FAILURE(status)) {
808                         return_ACPI_STATUS(status);
809                 }
810
811                 /* Start new output datum by merging with previous input datum */
812
813                 field_offset += obj_desc->common_field.access_byte_width;
814                 merged_datum = raw_datum >>
815                     (obj_desc->common_field.access_bit_width -
816                      obj_desc->common_field.start_field_bit_offset);
817                 mask = ACPI_INTEGER_MAX;
818
819                 if (i == datum_count) {
820                         break;
821                 }
822
823                 /* Get the next input datum from the buffer */
824
825                 buffer_offset += obj_desc->common_field.access_byte_width;
826                 ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
827                             ACPI_MIN(obj_desc->common_field.access_byte_width,
828                                      buffer_length - buffer_offset));
829                 merged_datum |=
830                     raw_datum << obj_desc->common_field.start_field_bit_offset;
831         }
832
833         /* Mask off any extra bits in the last datum */
834
835         buffer_tail_bits = (obj_desc->common_field.bit_length +
836                             obj_desc->common_field.start_field_bit_offset) %
837             obj_desc->common_field.access_bit_width;
838         if (buffer_tail_bits) {
839                 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
840         }
841
842         /* Write the last datum to the field */
843
844         merged_datum &= mask;
845         status = acpi_ex_write_with_update_rule(obj_desc,
846                                                 mask, merged_datum,
847                                                 field_offset);
848
849         return_ACPI_STATUS(status);
850 }