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     						  &current_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