File: /usr/src/linux/drivers/acpi/executer/exfldio.c
1 /******************************************************************************
2 *
3 * Module Name: exfldio - Aml Field I/O
4 * $Revision: 64 $
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 "acinterp.h"
29 #include "amlcode.h"
30 #include "acnamesp.h"
31 #include "achware.h"
32 #include "acevents.h"
33 #include "acdispat.h"
34
35
36 #define _COMPONENT ACPI_EXECUTER
37 MODULE_NAME ("exfldio")
38
39
40 /*******************************************************************************
41 *
42 * FUNCTION: Acpi_ex_setup_field
43 *
44 * PARAMETERS: *Obj_desc - Field to be read or written
45 * Field_datum_byte_offset - Current offset into the field
46 *
47 * RETURN: Status
48 *
49 * DESCRIPTION: Common processing for Acpi_ex_extract_from_field and
50 * Acpi_ex_insert_into_field
51 *
52 ******************************************************************************/
53
54 acpi_status
55 acpi_ex_setup_field (
56 acpi_operand_object *obj_desc,
57 u32 field_datum_byte_offset)
58 {
59 acpi_status status = AE_OK;
60 acpi_operand_object *rgn_desc;
61
62
63 FUNCTION_TRACE_U32 ("Ex_setup_field", field_datum_byte_offset);
64
65
66 rgn_desc = obj_desc->common_field.region_obj;
67
68 if (ACPI_TYPE_REGION != rgn_desc->common.type) {
69 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %x %s\n",
70 rgn_desc->common.type, acpi_ut_get_type_name (rgn_desc->common.type)));
71 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
72 }
73
74
75 /*
76 * If the Region Address and Length have not been previously evaluated,
77 * evaluate them now and save the results.
78 */
79 if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) {
80
81 status = acpi_ds_get_region_arguments (rgn_desc);
82 if (ACPI_FAILURE (status)) {
83 return_ACPI_STATUS (status);
84 }
85 }
86
87
88 /*
89 * Validate the request. The entire request from the byte offset for a
90 * length of one field datum (access width) must fit within the region.
91 * (Region length is specified in bytes)
92 */
93 if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset +
94 field_datum_byte_offset +
95 obj_desc->common_field.access_byte_width)) {
96 if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
97 /*
98 * This is the case where the Access_type (Acc_word, etc.) is wider
99 * than the region itself. For example, a region of length one
100 * byte, and a field with Dword access specified.
101 */
102 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
103 "Field access width (%d bytes) too large for region size (%X)\n",
104 obj_desc->common_field.access_byte_width, rgn_desc->region.length));
105 }
106
107 /*
108 * Offset rounded up to next multiple of field width
109 * exceeds region length, indicate an error
110 */
111 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
112 "Field base+offset+width %X+%X+%X exceeds region size (%X bytes) field=%p region=%p\n",
113 obj_desc->common_field.base_byte_offset, field_datum_byte_offset,
114 obj_desc->common_field.access_byte_width,
115 rgn_desc->region.length, obj_desc, rgn_desc));
116
117 return_ACPI_STATUS (AE_AML_REGION_LIMIT);
118 }
119
120 return_ACPI_STATUS (AE_OK);
121 }
122
123
124 /*******************************************************************************
125 *
126 * FUNCTION: Acpi_ex_read_field_datum
127 *
128 * PARAMETERS: *Obj_desc - Field to be read
129 * *Value - Where to store value (must be 32 bits)
130 *
131 * RETURN: Status
132 *
133 * DESCRIPTION: Retrieve the value of the given field
134 *
135 ******************************************************************************/
136
137 acpi_status
138 acpi_ex_read_field_datum (
139 acpi_operand_object *obj_desc,
140 u32 field_datum_byte_offset,
141 u32 *value)
142 {
143 acpi_status status;
144 acpi_operand_object *rgn_desc;
145 ACPI_PHYSICAL_ADDRESS address;
146 u32 local_value;
147
148
149 FUNCTION_TRACE_U32 ("Ex_read_field_datum", field_datum_byte_offset);
150
151
152 if (!value) {
153 local_value = 0;
154 value = &local_value; /* support reads without saving value */
155 }
156
157 /* Clear the entire return buffer first, [Very Important!] */
158
159 *value = 0;
160
161
162 /*
163 * Buffer_fields - Read from a Buffer
164 * Other Fields - Read from a Operation Region.
165 */
166 switch (obj_desc->common.type) {
167 case ACPI_TYPE_BUFFER_FIELD:
168
169 /*
170 * For Buffer_fields, we only need to copy the data from the
171 * source buffer. Length is the field width in bytes.
172 */
173 MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer
174 + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset,
175 obj_desc->common_field.access_byte_width);
176 status = AE_OK;
177 break;
178
179
180 case INTERNAL_TYPE_REGION_FIELD:
181 case INTERNAL_TYPE_BANK_FIELD:
182
183 /*
184 * For other fields, we need to go through an Operation Region
185 * (Only types that will get here are Region_fields and Bank_fields)
186 */
187 status = acpi_ex_setup_field (obj_desc, field_datum_byte_offset);
188 if (ACPI_FAILURE (status)) {
189 return_ACPI_STATUS (status);
190 }
191
192
193 /*
194 * The physical address of this field datum is:
195 *
196 * 1) The base of the region, plus
197 * 2) The base offset of the field, plus
198 * 3) The current offset into the field
199 */
200 rgn_desc = obj_desc->common_field.region_obj;
201 address = rgn_desc->region.address + obj_desc->common_field.base_byte_offset +
202 field_datum_byte_offset;
203
204 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Region %s(%X) width %X base:off %X:%X at %8.8lX%8.8lX\n",
205 acpi_ut_get_region_name (rgn_desc->region.space_id),
206 rgn_desc->region.space_id, obj_desc->common_field.access_bit_width,
207 obj_desc->common_field.base_byte_offset, field_datum_byte_offset,
208 HIDWORD(address), LODWORD(address)));
209
210
211 /* Invoke the appropriate Address_space/Op_region handler */
212
213 status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_READ_ADR_SPACE,
214 address, obj_desc->common_field.access_bit_width, value);
215 if (status == AE_NOT_IMPLEMENTED) {
216 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) not implemented\n",
217 acpi_ut_get_region_name (rgn_desc->region.space_id),
218 rgn_desc->region.space_id));
219 }
220
221 else if (status == AE_NOT_EXIST) {
222 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) has no handler\n",
223 acpi_ut_get_region_name (rgn_desc->region.space_id),
224 rgn_desc->region.space_id));
225 }
226 break;
227
228
229 default:
230
231 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n",
232 obj_desc, acpi_ut_get_type_name (obj_desc->common.type)));
233 status = AE_AML_INTERNAL;
234 break;
235 }
236
237
238 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Returned value=%08lX \n", *value));
239
240 return_ACPI_STATUS (status);
241 }
242
243
244 /*******************************************************************************
245 *
246 * FUNCTION: Acpi_ex_get_buffer_datum
247 *
248 * PARAMETERS: Merged_datum - Value to store
249 * Buffer - Receiving buffer
250 * Byte_granularity - 1/2/4 Granularity of the field
251 * (aka Datum Size)
252 * Offset - Datum offset into the buffer
253 *
254 * RETURN: none
255 *
256 * DESCRIPTION: Store the merged datum to the buffer according to the
257 * byte granularity
258 *
259 ******************************************************************************/
260
261 static void
262 acpi_ex_get_buffer_datum(
263 u32 *datum,
264 void *buffer,
265 u32 byte_granularity,
266 u32 offset)
267 {
268
269 FUNCTION_ENTRY ();
270
271
272 switch (byte_granularity) {
273 case ACPI_FIELD_BYTE_GRANULARITY:
274 *datum = ((u8 *) buffer) [offset];
275 break;
276
277 case ACPI_FIELD_WORD_GRANULARITY:
278 MOVE_UNALIGNED16_TO_32 (datum, &(((u16 *) buffer) [offset]));
279 break;
280
281 case ACPI_FIELD_DWORD_GRANULARITY:
282 MOVE_UNALIGNED32_TO_32 (datum, &(((u32 *) buffer) [offset]));
283 break;
284 }
285 }
286
287
288 /*******************************************************************************
289 *
290 * FUNCTION: Acpi_ex_set_buffer_datum
291 *
292 * PARAMETERS: Merged_datum - Value to store
293 * Buffer - Receiving buffer
294 * Byte_granularity - 1/2/4 Granularity of the field
295 * (aka Datum Size)
296 * Offset - Datum offset into the buffer
297 *
298 * RETURN: none
299 *
300 * DESCRIPTION: Store the merged datum to the buffer according to the
301 * byte granularity
302 *
303 ******************************************************************************/
304
305 static void
306 acpi_ex_set_buffer_datum (
307 u32 merged_datum,
308 void *buffer,
309 u32 byte_granularity,
310 u32 offset)
311 {
312
313 FUNCTION_ENTRY ();
314
315
316 switch (byte_granularity) {
317 case ACPI_FIELD_BYTE_GRANULARITY:
318 ((u8 *) buffer) [offset] = (u8) merged_datum;
319 break;
320
321 case ACPI_FIELD_WORD_GRANULARITY:
322 MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[offset]), &merged_datum);
323 break;
324
325 case ACPI_FIELD_DWORD_GRANULARITY:
326 MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[offset]), &merged_datum);
327 break;
328 }
329 }
330
331
332 /*******************************************************************************
333 *
334 * FUNCTION: Acpi_ex_extract_from_field
335 *
336 * PARAMETERS: *Obj_desc - Field to be read
337 * *Value - Where to store value
338 *
339 * RETURN: Status
340 *
341 * DESCRIPTION: Retrieve the value of the given field
342 *
343 ******************************************************************************/
344
345 acpi_status
346 acpi_ex_extract_from_field (
347 acpi_operand_object *obj_desc,
348 void *buffer,
349 u32 buffer_length)
350 {
351 acpi_status status;
352 u32 field_datum_byte_offset;
353 u32 datum_offset;
354 u32 previous_raw_datum;
355 u32 this_raw_datum = 0;
356 u32 merged_datum = 0;
357 u32 byte_field_length;
358 u32 datum_count;
359
360
361 FUNCTION_TRACE ("Ex_extract_from_field");
362
363
364 /*
365 * The field must fit within the caller's buffer
366 */
367 byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
368 if (byte_field_length > buffer_length) {
369 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Field size %X (bytes) too large for buffer (%X)\n",
370 byte_field_length, buffer_length));
371
372 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
373 }
374
375 /* Convert field byte count to datum count, round up if necessary */
376
377 datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width);
378
379 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
380 "Byte_len=%x, Datum_len=%x, Bit_gran=%x, Byte_gran=%x\n",
381 byte_field_length, datum_count, obj_desc->common_field.access_bit_width,
382 obj_desc->common_field.access_byte_width));
383
384
385 /*
386 * Clear the caller's buffer (the whole buffer length as given)
387 * This is very important, especially in the cases where a byte is read,
388 * but the buffer is really a u32 (4 bytes).
389 */
390 MEMSET (buffer, 0, buffer_length);
391
392 /* Read the first raw datum to prime the loop */
393
394 field_datum_byte_offset = 0;
395 datum_offset= 0;
396
397 status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, &previous_raw_datum);
398 if (ACPI_FAILURE (status)) {
399 return_ACPI_STATUS (status);
400 }
401
402
403 /* We might actually be done if the request fits in one datum */
404
405 if ((datum_count == 1) &&
406 (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) {
407 /* 1) Shift the valid data bits down to start at bit 0 */
408
409 merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset);
410
411 /* 2) Mask off any upper unused bits (bits not part of the field) */
412
413 if (obj_desc->common_field.end_buffer_valid_bits) {
414 merged_datum &= MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);
415 }
416
417 /* Store the datum to the caller buffer */
418
419 acpi_ex_set_buffer_datum (merged_datum, buffer, obj_desc->common_field.access_byte_width,
420 datum_offset);
421
422 return_ACPI_STATUS (AE_OK);
423 }
424
425
426 /* We need to get more raw data to complete one or more field data */
427
428 while (datum_offset < datum_count) {
429 field_datum_byte_offset += obj_desc->common_field.access_byte_width;
430
431 /*
432 * If the field is aligned on a byte boundary, we don't want
433 * to perform a final read, since this would potentially read
434 * past the end of the region.
435 *
436 * TBD: [Investigate] It may make more sense to just split the aligned
437 * and non-aligned cases since the aligned case is so very simple,
438 */
439 if ((obj_desc->common_field.start_field_bit_offset != 0) ||
440 ((obj_desc->common_field.start_field_bit_offset == 0) &&
441 (datum_offset < (datum_count -1)))) {
442 /*
443 * Get the next raw datum, it contains some or all bits
444 * of the current field datum
445 */
446 status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset, &this_raw_datum);
447 if (ACPI_FAILURE (status)) {
448 return_ACPI_STATUS (status);
449 }
450 }
451
452 /*
453 * Create the (possibly) merged datum to be stored to the caller buffer
454 */
455 if (obj_desc->common_field.start_field_bit_offset == 0) {
456 /* Field is not skewed and we can just copy the datum */
457
458 merged_datum = previous_raw_datum;
459 }
460
461 else {
462 /*
463 * Put together the appropriate bits of the two raw data to make a
464 * single complete field datum
465 *
466 * 1) Normalize the first datum down to bit 0
467 */
468 merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset);
469
470 /* 2) Insert the second datum "above" the first datum */
471
472 merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits);
473
474 if ((datum_offset >= (datum_count -1))) {
475 /*
476 * This is the last iteration of the loop. We need to clear
477 * any unused bits (bits that are not part of this field) that
478 * came from the last raw datum before we store the final
479 * merged datum into the caller buffer.
480 */
481 if (obj_desc->common_field.end_buffer_valid_bits) {
482 merged_datum &=
483 MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);
484 }
485 }
486 }
487
488
489 /*
490 * Store the merged field datum in the caller's buffer, according to
491 * the granularity of the field (size of each datum).
492 */
493 acpi_ex_set_buffer_datum (merged_datum, buffer, obj_desc->common_field.access_byte_width,
494 datum_offset);
495
496 /*
497 * Save the raw datum that was just acquired since it may contain bits
498 * of the *next* field datum. Update offsets
499 */
500 previous_raw_datum = this_raw_datum;
501 datum_offset++;
502 }
503
504
505 return_ACPI_STATUS (AE_OK);
506 }
507
508
509 /*******************************************************************************
510 *
511 * FUNCTION: Acpi_ex_write_field_datum
512 *
513 * PARAMETERS: *Obj_desc - Field to be set
514 * Value - Value to store
515 *
516 * RETURN: Status
517 *
518 * DESCRIPTION: Store the value into the given field
519 *
520 ******************************************************************************/
521
522 static acpi_status
523 acpi_ex_write_field_datum (
524 acpi_operand_object *obj_desc,
525 u32 field_datum_byte_offset,
526 u32 value)
527 {
528 acpi_status status = AE_OK;
529 acpi_operand_object *rgn_desc = NULL;
530 ACPI_PHYSICAL_ADDRESS address;
531
532
533 FUNCTION_TRACE_U32 ("Ex_write_field_datum", field_datum_byte_offset);
534
535
536 /*
537 * Buffer_fields - Read from a Buffer
538 * Other Fields - Read from a Operation Region.
539 */
540 switch (obj_desc->common.type) {
541 case ACPI_TYPE_BUFFER_FIELD:
542
543 /*
544 * For Buffer_fields, we only need to copy the data to the
545 * target buffer. Length is the field width in bytes.
546 */
547 MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer
548 + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset,
549 &value, obj_desc->common_field.access_byte_width);
550 status = AE_OK;
551 break;
552
553
554 case INTERNAL_TYPE_REGION_FIELD:
555 case INTERNAL_TYPE_BANK_FIELD:
556
557 /*
558 * For other fields, we need to go through an Operation Region
559 * (Only types that will get here are Region_fields and Bank_fields)
560 */
561 status = acpi_ex_setup_field (obj_desc, field_datum_byte_offset);
562 if (ACPI_FAILURE (status)) {
563 return_ACPI_STATUS (status);
564 }
565
566 /*
567 * The physical address of this field datum is:
568 *
569 * 1) The base of the region, plus
570 * 2) The base offset of the field, plus
571 * 3) The current offset into the field
572 */
573 rgn_desc = obj_desc->common_field.region_obj;
574 address = rgn_desc->region.address +
575 obj_desc->common_field.base_byte_offset +
576 field_datum_byte_offset;
577
578 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
579 "Store %X in Region %s(%X) at %8.8lX%8.8lX width %X\n",
580 value, acpi_ut_get_region_name (rgn_desc->region.space_id),
581 rgn_desc->region.space_id, HIDWORD(address), LODWORD(address),
582 obj_desc->common_field.access_bit_width));
583
584 /* Invoke the appropriate Address_space/Op_region handler */
585
586 status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_WRITE_ADR_SPACE,
587 address, obj_desc->common_field.access_bit_width, &value);
588
589 if (status == AE_NOT_IMPLEMENTED) {
590 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
591 "**** Region type %s(%X) not implemented\n",
592 acpi_ut_get_region_name (rgn_desc->region.space_id),
593 rgn_desc->region.space_id));
594 }
595
596 else if (status == AE_NOT_EXIST) {
597 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
598 "**** Region type %s(%X) does not have a handler\n",
599 acpi_ut_get_region_name (rgn_desc->region.space_id),
600 rgn_desc->region.space_id));
601 }
602
603 break;
604
605
606 default:
607
608 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n",
609 obj_desc, acpi_ut_get_type_name (obj_desc->common.type)));
610 status = AE_AML_INTERNAL;
611 break;
612 }
613
614
615 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value written=%08lX \n", value));
616 return_ACPI_STATUS (status);
617 }
618
619
620 /*******************************************************************************
621 *
622 * FUNCTION: Acpi_ex_write_field_datum_with_update_rule
623 *
624 * PARAMETERS: *Obj_desc - Field to be set
625 * Value - Value to store
626 *
627 * RETURN: Status
628 *
629 * DESCRIPTION: Apply the field update rule to a field write
630 *
631 ******************************************************************************/
632
633 static acpi_status
634 acpi_ex_write_field_datum_with_update_rule (
635 acpi_operand_object *obj_desc,
636 u32 mask,
637 u32 field_value,
638 u32 field_datum_byte_offset)
639 {
640 acpi_status status = AE_OK;
641 u32 merged_value;
642 u32 current_value;
643
644
645 FUNCTION_TRACE ("Ex_write_field_datum_with_update_rule");
646
647
648 /* Start with the new bits */
649
650 merged_value = field_value;
651
652
653 /* If the mask is all ones, we don't need to worry about the update rule */
654
655 if (mask != ACPI_UINT32_MAX) {
656 /* Decode the update rule */
657
658 switch (obj_desc->common_field.update_rule) {
659
660 case UPDATE_PRESERVE:
661
662 /*
663 * Check if update rule needs to be applied (not if mask is all
664 * ones) The left shift drops the bits we want to ignore.
665 */
666 if ((~mask << (sizeof (mask) * 8 -
667 obj_desc->common_field.access_bit_width)) != 0) {
668 /*
669 * Read the current contents of the byte/word/dword containing
670 * the field, and merge with the new field value.
671 */
672 status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset,
673 ¤t_value);
674 merged_value |= (current_value & ~mask);
675 }
676 break;
677
678
679 case UPDATE_WRITE_AS_ONES:
680
681 /* Set positions outside the field to all ones */
682
683 merged_value |= ~mask;
684 break;
685
686
687 case UPDATE_WRITE_AS_ZEROS:
688
689 /* Set positions outside the field to all zeros */
690
691 merged_value &= mask;
692 break;
693
694
695 default:
696 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
697 "Write_with_update_rule: Unknown Update_rule setting: %x\n",
698 obj_desc->common_field.update_rule));
699 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
700 break;
701 }
702 }
703
704
705 /* Write the merged value */
706
707 status = acpi_ex_write_field_datum (obj_desc, field_datum_byte_offset,
708 merged_value);
709
710 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Mask %X Datum_offset %X Value %X, Merged_value %X\n",
711 mask, field_datum_byte_offset, field_value, merged_value));
712
713 return_ACPI_STATUS (status);
714 }
715
716
717 /*******************************************************************************
718 *
719 * FUNCTION: Acpi_ex_insert_into_field
720 *
721 * PARAMETERS: *Obj_desc - Field to be set
722 * Buffer - Value to store
723 *
724 * RETURN: Status
725 *
726 * DESCRIPTION: Store the value into the given field
727 *
728 ******************************************************************************/
729
730 acpi_status
731 acpi_ex_insert_into_field (
732 acpi_operand_object *obj_desc,
733 void *buffer,
734 u32 buffer_length)
735 {
736 acpi_status status;
737 u32 field_datum_byte_offset;
738 u32 datum_offset;
739 u32 mask;
740 u32 merged_datum;
741 u32 previous_raw_datum;
742 u32 this_raw_datum;
743 u32 byte_field_length;
744 u32 datum_count;
745
746
747 FUNCTION_TRACE ("Ex_insert_into_field");
748
749
750 /*
751 * Incoming buffer must be at least as long as the field, we do not
752 * allow "partial" field writes. We do not care if the buffer is
753 * larger than the field, this typically happens when an integer is
754 * written to a field that is actually smaller than an integer.
755 */
756 byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
757 if (buffer_length < byte_field_length) {
758 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer length %X too small for field %X\n",
759 buffer_length, byte_field_length));
760
761 /* TBD: Need a better error code */
762
763 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
764 }
765
766 /* Convert byte count to datum count, round up if necessary */
767
768 datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width);
769
770 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
771 "Byte_len=%x, Datum_len=%x, Bit_gran=%x, Byte_gran=%x\n",
772 byte_field_length, datum_count, obj_desc->common_field.access_bit_width,
773 obj_desc->common_field.access_byte_width));
774
775
776 /*
777 * Break the request into up to three parts (similar to an I/O request):
778 * 1) non-aligned part at start
779 * 2) aligned part in middle
780 * 3) non-aligned part at the end
781 */
782 field_datum_byte_offset = 0;
783 datum_offset= 0;
784
785 /* Get a single datum from the caller's buffer */
786
787 acpi_ex_get_buffer_datum (&previous_raw_datum, buffer,
788 obj_desc->common_field.access_byte_width, datum_offset);
789
790 /*
791 * Part1:
792 * Write a partial field datum if field does not begin on a datum boundary
793 * Note: The code in this section also handles the aligned case
794 *
795 * Construct Mask with 1 bits where the field is, 0 bits elsewhere
796 * (Only the bottom 5 bits of Bit_length are valid for a shift operation)
797 *
798 * Mask off bits that are "below" the field (if any)
799 */
800 mask = MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
801
802 /* If the field fits in one datum, may need to mask upper bits */
803
804 if ((obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM) &&
805 obj_desc->common_field.end_field_valid_bits) {
806 /* There are bits above the field, mask them off also */
807
808 mask &= MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
809 }
810
811 /* Shift and mask the value into the field position */
812
813 merged_datum = (previous_raw_datum << obj_desc->common_field.start_field_bit_offset);
814 merged_datum &= mask;
815
816 /* Apply the update rule (if necessary) and write the datum to the field */
817
818 status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask, merged_datum,
819 field_datum_byte_offset);
820 if (ACPI_FAILURE (status)) {
821 return_ACPI_STATUS (status);
822 }
823
824 /* If the entire field fits within one datum, we are done. */
825
826 if ((datum_count == 1) &&
827 (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) {
828 return_ACPI_STATUS (AE_OK);
829 }
830
831 /*
832 * Part2:
833 * Write the aligned data.
834 *
835 * We don't need to worry about the update rule for these data, because
836 * all of the bits in each datum are part of the field.
837 *
838 * The last datum must be special cased because it might contain bits
839 * that are not part of the field -- therefore the "update rule" must be
840 * applied in Part3 below.
841 */
842 while (datum_offset < datum_count) {
843 datum_offset++;
844 field_datum_byte_offset += obj_desc->common_field.access_byte_width;
845
846 /*
847 * Get the next raw buffer datum. It may contain bits of the previous
848 * field datum
849 */
850 acpi_ex_get_buffer_datum (&this_raw_datum, buffer,
851 obj_desc->common_field.access_byte_width, datum_offset);
852
853 /* Create the field datum based on the field alignment */
854
855 if (obj_desc->common_field.start_field_bit_offset != 0) {
856 /*
857 * Put together appropriate bits of the two raw buffer data to make
858 * a single complete field datum
859 */
860 merged_datum =
861 (previous_raw_datum >> obj_desc->common_field.datum_valid_bits) |
862 (this_raw_datum << obj_desc->common_field.start_field_bit_offset);
863 }
864
865 else {
866 /* Field began aligned on datum boundary */
867
868 merged_datum = this_raw_datum;
869 }
870
871
872 /*
873 * Special handling for the last datum if the field does NOT end on
874 * a datum boundary. Update Rule must be applied to the bits outside
875 * the field.
876 */
877 if ((datum_offset == datum_count) &&
878 obj_desc->common_field.end_field_valid_bits) {
879 /*
880 * Part3:
881 * This is the last datum and the field does not end on a datum boundary.
882 * Build the partial datum and write with the update rule.
883 */
884
885 /* Mask off the unused bits above (after) the end-of-field */
886
887 mask = MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
888 merged_datum &= mask;
889
890 /* Write the last datum with the update rule */
891
892 status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask,
893 merged_datum, field_datum_byte_offset);
894 if (ACPI_FAILURE (status)) {
895 return_ACPI_STATUS (status);
896 }
897 }
898
899 else {
900 /* Normal case -- write the completed datum */
901
902 status = acpi_ex_write_field_datum (obj_desc,
903 field_datum_byte_offset, merged_datum);
904 if (ACPI_FAILURE (status)) {
905 return_ACPI_STATUS (status);
906 }
907 }
908
909 /*
910 * Save the most recent datum since it may contain bits of the *next*
911 * field datum. Update current byte offset.
912 */
913 previous_raw_datum = this_raw_datum;
914 }
915
916
917 return_ACPI_STATUS (status);
918 }
919
920
921