11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Module Name: exfldio - Aml Field I/O
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
877848130e53b06c22fe37a7b6acbb82bb3e9bfbaBob Moore * Copyright (C) 2000 - 2012, Intel Corp.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Redistribution and use in source and binary forms, with or without
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modification, are permitted provided that the following conditions
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * are met:
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Redistributions of source code must retain the above copyright
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    notice, this list of conditions, and the following disclaimer,
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    without modification.
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. Redistributions in binary form must reproduce at minimum a disclaimer
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    substantially similar to the "NO WARRANTY" disclaimer below
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    ("Disclaimer") and any redistribution must be conditioned upon
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    including a substantially similar Disclaimer requirement for further
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    binary redistribution.
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. Neither the names of the above-listed copyright holders nor the names
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    of any contributors may be used to endorse or promote products derived
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    from this software without specific prior written permission.
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alternatively, this software may be distributed under the terms of the
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License ("GPL") version 2 as published by the Free
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software Foundation.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NO WARRANTY
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * POSSIBILITY OF SUCH DAMAGES.
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi.h>
45e2f7a7772880458edff1b1cc5a988947229fac26Len Brown#include "accommon.h"
46e2f7a7772880458edff1b1cc5a988947229fac26Len Brown#include "acinterp.h"
47e2f7a7772880458edff1b1cc5a988947229fac26Len Brown#include "amlcode.h"
48e2f7a7772880458edff1b1cc5a988947229fac26Len Brown#include "acevents.h"
49e2f7a7772880458edff1b1cc5a988947229fac26Len Brown#include "acdispat.h"
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT          ACPI_EXECUTER
524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen BrownACPI_MODULE_NAME("exfldio")
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5444f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore/* Local prototypes */
5544f6c01242da4e162f28d8e1216a8c7a91174605Robert Moorestatic acpi_status
564be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		       u32 field_datum_byte_offset,
585df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore		       u64 *value, u32 read_write);
5944f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore
6044f6c01242da4e162f28d8e1216a8c7a91174605Robert Moorestatic u8
615df7e6cb42da36c7d878239bebc81907b15f3943Bob Mooreacpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
6244f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore
6344f6c01242da4e162f28d8e1216a8c7a91174605Robert Moorestatic acpi_status
644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_setup_region(union acpi_operand_object *obj_desc,
654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		     u32 field_datum_byte_offset);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_setup_region
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7144f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore * PARAMETERS:  obj_desc                - Field to be read or written
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              field_datum_byte_offset - Byte offset of this datum within the
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                        parent field
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      Status
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              acpi_ex_insert_into_field. Initialize the Region if necessary and
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              validate the request.
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8344f6c01242da4e162f28d8e1216a8c7a91174605Robert Moorestatic acpi_status
844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_setup_region(union acpi_operand_object *obj_desc,
854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		     u32 field_datum_byte_offset)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status = AE_OK;
884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	union acpi_operand_object *rgn_desc;
89ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	u8 space_id;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rgn_desc = obj_desc->common_field.region_obj;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We must have a valid region */
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
973371c19c294a4cb3649aa4e84606be8a1d999e61Bob Moore	if (rgn_desc->common.type != ACPI_TYPE_REGION) {
98f6a22b0bc417042e83117f52ab1a03696af185abBob Moore		ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)",
993371c19c294a4cb3649aa4e84606be8a1d999e61Bob Moore			    rgn_desc->common.type,
100b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    acpi_ut_get_object_type_name(rgn_desc)));
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
105ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	space_id = rgn_desc->region.space_id;
106ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore
107ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	/* Validate the Space ID */
108ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore
109ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	if (!acpi_is_valid_space_id(space_id)) {
110ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore		ACPI_ERROR((AE_INFO,
111ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore			    "Invalid/unknown Address Space ID: 0x%2.2X",
112ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore			    space_id));
113ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
114ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	}
115ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the Region Address and Length have not been previously evaluated,
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * evaluate them now and save the results.
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
1214be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		status = acpi_ds_get_region_arguments(rgn_desc);
1224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE(status)) {
1234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(status);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1277cb7f45c7feef43c8f71f5cfedfc0b19be2142f7Len Brown	/* Exit if Address/Length have been disallowed by the host OS */
1287cb7f45c7feef43c8f71f5cfedfc0b19be2142f7Len Brown
1297cb7f45c7feef43c8f71f5cfedfc0b19be2142f7Len Brown	if (rgn_desc->common.flags & AOPOBJ_INVALID) {
1307cb7f45c7feef43c8f71f5cfedfc0b19be2142f7Len Brown		return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
1317cb7f45c7feef43c8f71f5cfedfc0b19be2142f7Len Brown	}
1327cb7f45c7feef43c8f71f5cfedfc0b19be2142f7Len Brown
133b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	/*
1342da120b6847f85c406f9afa13853e2755684389eBob Moore	 * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
13509387b43153953006471dbb06ece6bf779d10937Bob Moore	 * address space and the request cannot be directly validated
136b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	 */
137ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	if (space_id == ACPI_ADR_SPACE_SMBUS ||
1382da120b6847f85c406f9afa13853e2755684389eBob Moore	    space_id == ACPI_ADR_SPACE_GSBUS ||
139ec4636669bf9c6ff157121ab42709650a9e0cc2aBob Moore	    space_id == ACPI_ADR_SPACE_IPMI) {
14052fc0b026e99b5d5d585095148d997d5634bbc25Bob Moore
1416557a49a443a347d24aed58076365432ded30edcLin Ming		/* SMBus or IPMI has a non-linear address space */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1434be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return_ACPI_STATUS(AE_OK);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ACPI_UNDER_DEVELOPMENT
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the Field access is any_acc, we can now compute the optimal
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * access (because we know know the length of the parent region)
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
1514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE(status)) {
1524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(status);
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Validate the request.  The entire request from the byte offset for a
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * length of one field datum (access width) must fit within the region.
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * (Region length is specified in bytes)
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1624119532c95547821dbe72d6916dfa1b2148475b3Bob Moore	if (rgn_desc->region.length <
16309387b43153953006471dbb06ece6bf779d10937Bob Moore	    (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
1644119532c95547821dbe72d6916dfa1b2148475b3Bob Moore	     obj_desc->common_field.access_byte_width)) {
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (acpi_gbl_enable_interpreter_slack) {
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Slack mode only:  We will go ahead and allow access to this
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * field if it is within the region length rounded up to the next
16967a119f990063f5662574f6d6414fe9bc5ece86aBob Moore			 * access width boundary. acpi_size cast for 64-bit compile.
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
1714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			if (ACPI_ROUND_UP(rgn_desc->region.length,
1724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  obj_desc->common_field.
1734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  access_byte_width) >=
17467a119f990063f5662574f6d6414fe9bc5ece86aBob Moore			    ((acpi_size) obj_desc->common_field.
17567a119f990063f5662574f6d6414fe9bc5ece86aBob Moore			     base_byte_offset +
17667a119f990063f5662574f6d6414fe9bc5ece86aBob Moore			     obj_desc->common_field.access_byte_width +
17767a119f990063f5662574f6d6414fe9bc5ece86aBob Moore			     field_datum_byte_offset)) {
1784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				return_ACPI_STATUS(AE_OK);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1824be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (rgn_desc->region.length <
1834be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    obj_desc->common_field.access_byte_width) {
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * This is the case where the access_type (acc_word, etc.) is wider
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * than the region itself.  For example, a region of length one
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * byte, and a field with Dword access specified.
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
189b8e4d89357fc434618a59c1047cac72641191805Bob Moore			ACPI_ERROR((AE_INFO,
190f6a22b0bc417042e83117f52ab1a03696af185abBob Moore				    "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
191b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    acpi_ut_get_node_name(obj_desc->
192b8e4d89357fc434618a59c1047cac72641191805Bob Moore							  common_field.node),
193b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    obj_desc->common_field.access_byte_width,
194b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    acpi_ut_get_node_name(rgn_desc->region.
195b8e4d89357fc434618a59c1047cac72641191805Bob Moore							  node),
196b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    rgn_desc->region.length));
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Offset rounded up to next multiple of field width
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * exceeds region length, indicate an error
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
203b8e4d89357fc434618a59c1047cac72641191805Bob Moore		ACPI_ERROR((AE_INFO,
204f6a22b0bc417042e83117f52ab1a03696af185abBob Moore			    "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
205b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    acpi_ut_get_node_name(obj_desc->common_field.node),
206b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    obj_desc->common_field.base_byte_offset,
207b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    field_datum_byte_offset,
208b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    obj_desc->common_field.access_byte_width,
209b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    acpi_ut_get_node_name(rgn_desc->region.node),
210b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    rgn_desc->region.length));
2114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
2124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return_ACPI_STATUS(AE_AML_REGION_LIMIT);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return_ACPI_STATUS(AE_OK);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_access_region
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
22244f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore * PARAMETERS:  obj_desc                - Field to be read
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              field_datum_byte_offset - Byte offset of this datum within the
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                        parent field
22544f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore *              Value                   - Where to store value (must at least
2265df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore *                                        64 bits)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              Function                - Read or Write flag plus other region-
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                        dependent flags
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      Status
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Read or Write a single field datum to an Operation Region.
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsacpi_status
2374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_access_region(union acpi_operand_object *obj_desc,
2385df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore		      u32 field_datum_byte_offset, u64 *value, u32 function)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status;
2414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	union acpi_operand_object *rgn_desc;
242f5407af3f271ed4cd6655cf30d419d77e0f8bfaaBob Moore	u32 region_offset;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
244b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	ACPI_FUNCTION_TRACE(ex_access_region);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Ensure that the region operands are fully evaluated and verify
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the validity of the request
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2504be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
2514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	if (ACPI_FAILURE(status)) {
2524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return_ACPI_STATUS(status);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The physical address of this field datum is:
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 1) The base of the region, plus
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 2) The base offset of the field, plus
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 3) The current offset into the field
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rgn_desc = obj_desc->common_field.region_obj;
263f5407af3f271ed4cd6655cf30d419d77e0f8bfaaBob Moore	region_offset =
2644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	    obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((function & ACPI_IO_MASK) == ACPI_READ) {
2674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
2684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	} else {
2694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
273f3d2e7865c816258c699ff965768e46b50d536d3Bob Moore			      " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
2744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			      acpi_ut_get_region_name(rgn_desc->region.
2754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						      space_id),
2764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			      rgn_desc->region.space_id,
2774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			      obj_desc->common_field.access_byte_width,
2784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			      obj_desc->common_field.base_byte_offset,
279b7f9f04228eae2cf5adc2ffeb494d4970a8dd8a5Bob Moore			      field_datum_byte_offset, ACPI_CAST_PTR(void,
280f5407af3f271ed4cd6655cf30d419d77e0f8bfaaBob Moore								     (rgn_desc->
281f5407af3f271ed4cd6655cf30d419d77e0f8bfaaBob Moore								      region.
282f5407af3f271ed4cd6655cf30d419d77e0f8bfaaBob Moore								      address +
283f5407af3f271ed4cd6655cf30d419d77e0f8bfaaBob Moore								      region_offset))));
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Invoke the appropriate address_space/op_region handler */
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2879ce81784c9c0396a6a6be05248928a71134fe60bBob Moore	status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
2889ce81784c9c0396a6a6be05248928a71134fe60bBob Moore						function, region_offset,
2899ce81784c9c0396a6a6be05248928a71134fe60bBob Moore						ACPI_MUL_8(obj_desc->
2909ce81784c9c0396a6a6be05248928a71134fe60bBob Moore							   common_field.
2919ce81784c9c0396a6a6be05248928a71134fe60bBob Moore							   access_byte_width),
2929ce81784c9c0396a6a6be05248928a71134fe60bBob Moore						value);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	if (ACPI_FAILURE(status)) {
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status == AE_NOT_IMPLEMENTED) {
296b8e4d89357fc434618a59c1047cac72641191805Bob Moore			ACPI_ERROR((AE_INFO,
2971b74dfb2f735454031584dc8162f8f27aa5265bfBob Moore				    "Region %s (ID=%u) not implemented",
298b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    acpi_ut_get_region_name(rgn_desc->region.
299b8e4d89357fc434618a59c1047cac72641191805Bob Moore							    space_id),
300b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    rgn_desc->region.space_id));
3014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		} else if (status == AE_NOT_EXIST) {
302b8e4d89357fc434618a59c1047cac72641191805Bob Moore			ACPI_ERROR((AE_INFO,
3031b74dfb2f735454031584dc8162f8f27aa5265bfBob Moore				    "Region %s (ID=%u) has no handler",
304b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    acpi_ut_get_region_name(rgn_desc->region.
305b8e4d89357fc434618a59c1047cac72641191805Bob Moore							    space_id),
306b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    rgn_desc->region.space_id));
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return_ACPI_STATUS(status);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_register_overflow
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31744f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore * PARAMETERS:  obj_desc                - Register(Field) to be written
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              Value                   - Value to be stored
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      TRUE if value overflows the field, FALSE otherwise
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Check if a value is out of range of the field being written.
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              Used to check if the values written to Index and Bank registers
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              are out of range.  Normally, the value is simply truncated
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              to fit the field, but this case is most likely a serious
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              coding error in the ASL.
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33044f6c01242da4e162f28d8e1216a8c7a91174605Robert Moorestatic u8
3315df7e6cb42da36c7d878239bebc81907b15f3943Bob Mooreacpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33346dfb09c024a1a92ead63b40f6993dcb5eb7d153Bob Moore	ACPI_FUNCTION_NAME(ex_register_overflow);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The field is large enough to hold the maximum integer, so we can
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * never overflow it.
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (FALSE);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3435df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) {
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The Value is larger than the maximum value that can fit into
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the register.
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
34846dfb09c024a1a92ead63b40f6993dcb5eb7d153Bob Moore		ACPI_ERROR((AE_INFO,
34946dfb09c024a1a92ead63b40f6993dcb5eb7d153Bob Moore			    "Index value 0x%8.8X%8.8X overflows field width 0x%X",
35046dfb09c024a1a92ead63b40f6993dcb5eb7d153Bob Moore			    ACPI_FORMAT_UINT64(value),
35146dfb09c024a1a92ead63b40f6993dcb5eb7d153Bob Moore			    obj_desc->common_field.bit_length));
35246dfb09c024a1a92ead63b40f6993dcb5eb7d153Bob Moore
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (TRUE);
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The Value will fit into the field with no truncation */
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (FALSE);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_field_datum_io
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
36544f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore * PARAMETERS:  obj_desc                - Field to be read
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              field_datum_byte_offset - Byte offset of this datum within the
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                        parent field
36844f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore *              Value                   - Where to store value (must be 64 bits)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              read_write              - Read or Write flag
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      Status
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Read or Write a single datum of a field.  The field_type is
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              demultiplexed here to handle the different types of fields
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              (buffer_field, region_field, index_field, bank_field)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37944f6c01242da4e162f28d8e1216a8c7a91174605Robert Moorestatic acpi_status
3804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
3815df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore		       u32 field_datum_byte_offset, u64 *value, u32 read_write)
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3834be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status;
3845df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 local_value;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
386b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (read_write == ACPI_READ) {
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!value) {
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			local_value = 0;
39144f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore
39244f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore			/* To support reads without saving return value */
39344f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore			value = &local_value;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Clear the entire return buffer first, [Very Important!] */
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*value = 0;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The four types of fields are:
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * buffer_field - Read/write from/to a Buffer
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * region_field - Read/write from/to a Operation Region.
40644f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	 * bank_field  - Write to a Bank Register, then read/write from/to an
40744f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	 *               operation_region
40844f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	 * index_field - Write to an Index Register, then read/write from/to a
40944f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore	 *               Data Register
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4113371c19c294a4cb3649aa4e84606be8a1d999e61Bob Moore	switch (obj_desc->common.type) {
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_TYPE_BUFFER_FIELD:
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the buffer_field arguments have not been previously evaluated,
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * evaluate them now and save the results.
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
4184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			status = acpi_ds_get_buffer_field_arguments(obj_desc);
4194be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			if (ACPI_FAILURE(status)) {
4204be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				return_ACPI_STATUS(status);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (read_write == ACPI_READ) {
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Copy the data from the source buffer.
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Length is the field width in bytes.
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			ACPI_MEMCPY(value,
4304be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    (obj_desc->buffer_field.buffer_obj)->buffer.
4314be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    pointer +
4324be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    obj_desc->buffer_field.base_byte_offset +
4334be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    field_datum_byte_offset,
4344be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    obj_desc->common_field.access_byte_width);
4354be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		} else {
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Copy the data to the target buffer.
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Length is the field width in bytes.
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
4414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    pointer +
4424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    obj_desc->buffer_field.base_byte_offset +
4434be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    field_datum_byte_offset, value,
4444be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    obj_desc->common_field.access_byte_width);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = AE_OK;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_TYPE_LOCAL_BANK_FIELD:
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45244f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		/*
45344f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		 * Ensure that the bank_value is not beyond the capacity of
45444f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		 * the register
45544f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		 */
4564be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
4575df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore					      (u64) obj_desc->bank_field.
4585df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore					      value)) {
4594be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * For bank_fields, we must write the bank_value to the bank_register
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * (itself a region_field) before we can access the data.
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		status =
4674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
4684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					      &obj_desc->bank_field.value,
4694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					      sizeof(obj_desc->bank_field.
4704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						     value));
4714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE(status)) {
4724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(status);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Now that the Bank has been selected, fall through to the
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * region_field case and write the datum to the Operation Region
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*lint -fallthrough */
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_TYPE_LOCAL_REGION_FIELD:
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * For simple region_fields, we just directly access the owning
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Operation Region.
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		status =
4884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    acpi_ex_access_region(obj_desc, field_datum_byte_offset,
4894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  value, read_write);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case ACPI_TYPE_LOCAL_INDEX_FIELD:
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49444f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		/*
49544f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		 * Ensure that the index_value is not beyond the capacity of
49644f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		 * the register
49744f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore		 */
4984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
4995df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore					      (u64) obj_desc->index_field.
5005df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore					      value)) {
5014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Write the index value to the index_register (itself a region_field) */
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		field_datum_byte_offset += obj_desc->index_field.value;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5084be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
5094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  "Write to Index Register: Value %8.8X\n",
5104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				  field_datum_byte_offset));
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		status =
5134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
5144be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					      &field_datum_byte_offset,
5154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					      sizeof(field_datum_byte_offset));
5164be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE(status)) {
5174be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(status);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (read_write == ACPI_READ) {
52152fc0b026e99b5d5d585095148d997d5634bbc25Bob Moore
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Read the datum from the data_register */
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
524e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
525e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore					  "Read from Data Register\n"));
526e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore
5274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			status =
5284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    acpi_ex_extract_from_field(obj_desc->index_field.
5294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						       data_obj, value,
5305df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore						       sizeof(u64));
5314be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		} else {
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Write the datum to the data_register */
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
534e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
535e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore					  "Write to Data Register: Value %8.8X%8.8X\n",
536e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore					  ACPI_FORMAT_UINT64(*value)));
537e9a8c6a90953b65326881189a1f3782bb2f6d250Bob Moore
5384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			status =
5394be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    acpi_ex_insert_into_field(obj_desc->index_field.
5404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						      data_obj, value,
5415df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore						      sizeof(u64));
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
547f6a22b0bc417042e83117f52ab1a03696af185abBob Moore		ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u",
5483371c19c294a4cb3649aa4e84606be8a1d999e61Bob Moore			    obj_desc->common.type));
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = AE_AML_INTERNAL;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	if (ACPI_SUCCESS(status)) {
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (read_write == ACPI_READ) {
5554be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
556b27d65975c252ff774edff8e01f0a9fd46d8ab62Bob Moore					  "Value Read %8.8X%8.8X, Width %u\n",
5574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  ACPI_FORMAT_UINT64(*value),
5584be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  obj_desc->common_field.
5594be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  access_byte_width));
5604be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		} else {
5614be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
562b27d65975c252ff774edff8e01f0a9fd46d8ab62Bob Moore					  "Value Written %8.8X%8.8X, Width %u\n",
5634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  ACPI_FORMAT_UINT64(*value),
5644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  obj_desc->common_field.
5654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  access_byte_width));
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return_ACPI_STATUS(status);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_write_with_update_rule
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
57644f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore * PARAMETERS:  obj_desc                - Field to be written
57744f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore *              Mask                    - bitmask within field datum
57844f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore *              field_value             - Value to write
57944f6c01242da4e162f28d8e1216a8c7a91174605Robert Moore *              field_datum_byte_offset - Offset of datum within field
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      Status
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Apply the field update rule to a field write
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsacpi_status
5884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
5895df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore			       u64 mask,
5905df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore			       u64 field_value, u32 field_datum_byte_offset)
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status = AE_OK;
5935df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 merged_value;
5945df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 current_value;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
596b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start with the new bits  */
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	merged_value = field_value;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the mask is all ones, we don't need to worry about the update rule */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6045df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	if (mask != ACPI_UINT64_MAX) {
60552fc0b026e99b5d5d585095148d997d5634bbc25Bob Moore
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Decode the update rule */
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6084be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		switch (obj_desc->common_field.
6094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			field_flags & AML_FIELD_UPDATE_RULE_MASK) {
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case AML_FIELD_UPDATE_PRESERVE:
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Check if update rule needs to be applied (not if mask is all
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * ones)  The left shift drops the bits we want to ignore.
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
6164be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				       ACPI_MUL_8(obj_desc->common_field.
6174be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						  access_byte_width))) != 0) {
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * Read the current contents of the byte/word/dword containing
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * the field, and merge with the new field value.
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
6224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				status =
6234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				    acpi_ex_field_datum_io(obj_desc,
6244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown							   field_datum_byte_offset,
6254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown							   &current_value,
6264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown							   ACPI_READ);
6274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				if (ACPI_FAILURE(status)) {
6284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					return_ACPI_STATUS(status);
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				merged_value |= (current_value & ~mask);
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case AML_FIELD_UPDATE_WRITE_AS_ONES:
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Set positions outside the field to all ones */
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			merged_value |= ~mask;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Set positions outside the field to all zeros */
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			merged_value &= mask;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651b8e4d89357fc434618a59c1047cac72641191805Bob Moore			ACPI_ERROR((AE_INFO,
652f6a22b0bc417042e83117f52ab1a03696af185abBob Moore				    "Unknown UpdateRule value: 0x%X",
653b8e4d89357fc434618a59c1047cac72641191805Bob Moore				    (obj_desc->common_field.
654b8e4d89357fc434618a59c1047cac72641191805Bob Moore				     field_flags &
655b8e4d89357fc434618a59c1047cac72641191805Bob Moore				     AML_FIELD_UPDATE_RULE_MASK)));
6564be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6604be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
661b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore			  "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
6624be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  ACPI_FORMAT_UINT64(mask),
6634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  field_datum_byte_offset,
6644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  obj_desc->common_field.access_byte_width,
6654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  ACPI_FORMAT_UINT64(field_value),
6664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  ACPI_FORMAT_UINT64(merged_value)));
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write the merged value */
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
6714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					&merged_value, ACPI_WRITE);
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return_ACPI_STATUS(status);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_extract_from_field
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PARAMETERS:  obj_desc            - Field to be read
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              Buffer              - Where to store the field data
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              buffer_length       - Length of Buffer
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      Status
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Retrieve the current value of the given field
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsacpi_status
6914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
6924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			   void *buffer, u32 buffer_length)
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status;
6955df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 raw_datum;
6965df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 merged_datum;
6974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 field_offset = 0;
6984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 buffer_offset = 0;
6994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 buffer_tail_bits;
7004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 datum_count;
7014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 field_datum_count;
70209387b43153953006471dbb06ece6bf779d10937Bob Moore	u32 access_bit_width;
7034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 i;
7044be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
705b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	ACPI_FUNCTION_TRACE(ex_extract_from_field);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Validate target buffer and clear it */
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	if (buffer_length <
7104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
711b8e4d89357fc434618a59c1047cac72641191805Bob Moore		ACPI_ERROR((AE_INFO,
712f6a22b0bc417042e83117f52ab1a03696af185abBob Moore			    "Field size %u (bits) is too large for buffer (%u)",
713b8e4d89357fc434618a59c1047cac72641191805Bob Moore			    obj_desc->common_field.bit_length, buffer_length));
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
71709387b43153953006471dbb06ece6bf779d10937Bob Moore
7184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	ACPI_MEMSET(buffer, 0, buffer_length);
71909387b43153953006471dbb06ece6bf779d10937Bob Moore	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
72009387b43153953006471dbb06ece6bf779d10937Bob Moore
72109387b43153953006471dbb06ece6bf779d10937Bob Moore	/* Handle the simple case here */
72209387b43153953006471dbb06ece6bf779d10937Bob Moore
72309387b43153953006471dbb06ece6bf779d10937Bob Moore	if ((obj_desc->common_field.start_field_bit_offset == 0) &&
72409387b43153953006471dbb06ece6bf779d10937Bob Moore	    (obj_desc->common_field.bit_length == access_bit_width)) {
72509387b43153953006471dbb06ece6bf779d10937Bob Moore		status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
72609387b43153953006471dbb06ece6bf779d10937Bob Moore		return_ACPI_STATUS(status);
72709387b43153953006471dbb06ece6bf779d10937Bob Moore	}
72809387b43153953006471dbb06ece6bf779d10937Bob Moore
72909387b43153953006471dbb06ece6bf779d10937Bob Moore/* TBD: Move to common setup code */
73009387b43153953006471dbb06ece6bf779d10937Bob Moore
73109387b43153953006471dbb06ece6bf779d10937Bob Moore	/* Field algorithm is limited to sizeof(u64), truncate if needed */
73209387b43153953006471dbb06ece6bf779d10937Bob Moore
73309387b43153953006471dbb06ece6bf779d10937Bob Moore	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
73409387b43153953006471dbb06ece6bf779d10937Bob Moore		obj_desc->common_field.access_byte_width = sizeof(u64);
73509387b43153953006471dbb06ece6bf779d10937Bob Moore		access_bit_width = sizeof(u64) * 8;
73609387b43153953006471dbb06ece6bf779d10937Bob Moore	}
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Compute the number of datums (access width data items) */
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
74009387b43153953006471dbb06ece6bf779d10937Bob Moore	datum_count =
74109387b43153953006471dbb06ece6bf779d10937Bob Moore	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
74209387b43153953006471dbb06ece6bf779d10937Bob Moore			     access_bit_width);
74309387b43153953006471dbb06ece6bf779d10937Bob Moore
7444be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
7454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					     obj_desc->common_field.
7464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					     start_field_bit_offset,
7474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					     access_bit_width);
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Priming read from the field */
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	status =
7524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	    acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
7534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				   ACPI_READ);
7544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	if (ACPI_FAILURE(status)) {
7554be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		return_ACPI_STATUS(status);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	merged_datum =
7584be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	    raw_datum >> obj_desc->common_field.start_field_bit_offset;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read the rest of the field */
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i < field_datum_count; i++) {
76352fc0b026e99b5d5d585095148d997d5634bbc25Bob Moore
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Get next input datum from the field */
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		field_offset += obj_desc->common_field.access_byte_width;
7674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		status = acpi_ex_field_datum_io(obj_desc, field_offset,
7684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						&raw_datum, ACPI_READ);
7694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE(status)) {
7704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			return_ACPI_STATUS(status);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
773967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		/*
774967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * Merge with previous datum if necessary.
775967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 *
776967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * Note: Before the shift, check if the shift value will be larger than
777967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * the integer size. If so, there is no need to perform the operation.
778967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * This avoids the differences in behavior between different compilers
779967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * concerning shift values larger than the target data width.
780967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 */
78109387b43153953006471dbb06ece6bf779d10937Bob Moore		if (access_bit_width -
78209387b43153953006471dbb06ece6bf779d10937Bob Moore		    obj_desc->common_field.start_field_bit_offset <
783967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		    ACPI_INTEGER_BIT_SIZE) {
784967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore			merged_datum |=
78509387b43153953006471dbb06ece6bf779d10937Bob Moore			    raw_datum << (access_bit_width -
786967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore					  obj_desc->common_field.
787967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore					  start_field_bit_offset);
788967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		}
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == datum_count) {
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Write merged datum to target buffer */
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
7974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    ACPI_MIN(obj_desc->common_field.access_byte_width,
7984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				     buffer_length - buffer_offset));
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buffer_offset += obj_desc->common_field.access_byte_width;
8014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		merged_datum =
8024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    raw_datum >> obj_desc->common_field.start_field_bit_offset;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Mask off any extra bits in the last datum */
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80709387b43153953006471dbb06ece6bf779d10937Bob Moore	buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (buffer_tail_bits) {
8094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write the last datum to the buffer */
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8144be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
8154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    ACPI_MIN(obj_desc->common_field.access_byte_width,
8164be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			     buffer_length - buffer_offset));
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return_ACPI_STATUS(AE_OK);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FUNCTION:    acpi_ex_insert_into_field
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PARAMETERS:  obj_desc            - Field to be written
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              Buffer              - Data to be written
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              buffer_length       - Length of Buffer
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RETURN:      Status
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DESCRIPTION: Store the Buffer contents into the given field
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ******************************************************************************/
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsacpi_status
8364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
8374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			  void *buffer, u32 buffer_length)
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
83909387b43153953006471dbb06ece6bf779d10937Bob Moore	void *new_buffer;
8404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	acpi_status status;
8415df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 mask;
8425df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 width_mask;
8435df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 merged_datum;
8445df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore	u64 raw_datum = 0;
8454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 field_offset = 0;
8464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 buffer_offset = 0;
8474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 buffer_tail_bits;
8484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 datum_count;
8494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	u32 field_datum_count;
85009387b43153953006471dbb06ece6bf779d10937Bob Moore	u32 access_bit_width;
8519aa6169f471771324b476a90d9392daa06d63a2dBob Moore	u32 required_length;
85209387b43153953006471dbb06ece6bf779d10937Bob Moore	u32 i;
8534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown
854b229cf92eee616c7cb5ad8cdb35a19b119f00bc8Bob Moore	ACPI_FUNCTION_TRACE(ex_insert_into_field);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Validate input buffer */
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8589aa6169f471771324b476a90d9392daa06d63a2dBob Moore	new_buffer = NULL;
8599aa6169f471771324b476a90d9392daa06d63a2dBob Moore	required_length =
8609aa6169f471771324b476a90d9392daa06d63a2dBob Moore	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
8619aa6169f471771324b476a90d9392daa06d63a2dBob Moore	/*
8629aa6169f471771324b476a90d9392daa06d63a2dBob Moore	 * We must have a buffer that is at least as long as the field
8639aa6169f471771324b476a90d9392daa06d63a2dBob Moore	 * we are writing to.  This is because individual fields are
8649aa6169f471771324b476a90d9392daa06d63a2dBob Moore	 * indivisible and partial writes are not supported -- as per
8659aa6169f471771324b476a90d9392daa06d63a2dBob Moore	 * the ACPI specification.
8669aa6169f471771324b476a90d9392daa06d63a2dBob Moore	 */
8679aa6169f471771324b476a90d9392daa06d63a2dBob Moore	if (buffer_length < required_length) {
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8699aa6169f471771324b476a90d9392daa06d63a2dBob Moore		/* We need to create a new buffer */
8709aa6169f471771324b476a90d9392daa06d63a2dBob Moore
8719aa6169f471771324b476a90d9392daa06d63a2dBob Moore		new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
8729aa6169f471771324b476a90d9392daa06d63a2dBob Moore		if (!new_buffer) {
8739aa6169f471771324b476a90d9392daa06d63a2dBob Moore			return_ACPI_STATUS(AE_NO_MEMORY);
8749aa6169f471771324b476a90d9392daa06d63a2dBob Moore		}
8759aa6169f471771324b476a90d9392daa06d63a2dBob Moore
8769aa6169f471771324b476a90d9392daa06d63a2dBob Moore		/*
8779aa6169f471771324b476a90d9392daa06d63a2dBob Moore		 * Copy the original data to the new buffer, starting
8789aa6169f471771324b476a90d9392daa06d63a2dBob Moore		 * at Byte zero.  All unused (upper) bytes of the
8799aa6169f471771324b476a90d9392daa06d63a2dBob Moore		 * buffer will be 0.
8809aa6169f471771324b476a90d9392daa06d63a2dBob Moore		 */
8819aa6169f471771324b476a90d9392daa06d63a2dBob Moore		ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
8829aa6169f471771324b476a90d9392daa06d63a2dBob Moore		buffer = new_buffer;
8839aa6169f471771324b476a90d9392daa06d63a2dBob Moore		buffer_length = required_length;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
88609387b43153953006471dbb06ece6bf779d10937Bob Moore/* TBD: Move to common setup code */
88709387b43153953006471dbb06ece6bf779d10937Bob Moore
88809387b43153953006471dbb06ece6bf779d10937Bob Moore	/* Algo is limited to sizeof(u64), so cut the access_byte_width */
88909387b43153953006471dbb06ece6bf779d10937Bob Moore	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
89009387b43153953006471dbb06ece6bf779d10937Bob Moore		obj_desc->common_field.access_byte_width = sizeof(u64);
89109387b43153953006471dbb06ece6bf779d10937Bob Moore	}
89209387b43153953006471dbb06ece6bf779d10937Bob Moore
89309387b43153953006471dbb06ece6bf779d10937Bob Moore	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
89409387b43153953006471dbb06ece6bf779d10937Bob Moore
895967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	/*
896967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	 * Create the bitmasks used for bit insertion.
897967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	 * Note: This if/else is used to bypass compiler differences with the
898967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	 * shift operator
899967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	 */
90009387b43153953006471dbb06ece6bf779d10937Bob Moore	if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
9015df7e6cb42da36c7d878239bebc81907b15f3943Bob Moore		width_mask = ACPI_UINT64_MAX;
902967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	} else {
90309387b43153953006471dbb06ece6bf779d10937Bob Moore		width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
904967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	}
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
906967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	mask = width_mask &
907967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	    ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
908967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore
909967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore	/* Compute the number of datums (access width data items) */
9104119532c95547821dbe72d6916dfa1b2148475b3Bob Moore
9114119532c95547821dbe72d6916dfa1b2148475b3Bob Moore	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
91209387b43153953006471dbb06ece6bf779d10937Bob Moore				       access_bit_width);
9134119532c95547821dbe72d6916dfa1b2148475b3Bob Moore
9144119532c95547821dbe72d6916dfa1b2148475b3Bob Moore	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
9154119532c95547821dbe72d6916dfa1b2148475b3Bob Moore					     obj_desc->common_field.
9164119532c95547821dbe72d6916dfa1b2148475b3Bob Moore					     start_field_bit_offset,
9174119532c95547821dbe72d6916dfa1b2148475b3Bob Moore					     access_bit_width);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get initial Datum from the input buffer */
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9214be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	ACPI_MEMCPY(&raw_datum, buffer,
9224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    ACPI_MIN(obj_desc->common_field.access_byte_width,
9234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			     buffer_length - buffer_offset));
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	merged_datum =
9264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	    raw_datum << obj_desc->common_field.start_field_bit_offset;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write the entire field */
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i < field_datum_count; i++) {
93152fc0b026e99b5d5d585095148d997d5634bbc25Bob Moore
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Write merged datum to the target field */
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		merged_datum &= mask;
9354be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		status = acpi_ex_write_with_update_rule(obj_desc, mask,
9364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown							merged_datum,
9374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown							field_offset);
9384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		if (ACPI_FAILURE(status)) {
9399aa6169f471771324b476a90d9392daa06d63a2dBob Moore			goto exit;
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		field_offset += obj_desc->common_field.access_byte_width;
943967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore
944967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		/*
945967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * Start new output datum by merging with previous input datum
946967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * if necessary.
947967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 *
948967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * Note: Before the shift, check if the shift value will be larger than
949967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * the integer size. If so, there is no need to perform the operation.
950967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * This avoids the differences in behavior between different compilers
951967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 * concerning shift values larger than the target data width.
952967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		 */
95309387b43153953006471dbb06ece6bf779d10937Bob Moore		if ((access_bit_width -
954967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		     obj_desc->common_field.start_field_bit_offset) <
955967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		    ACPI_INTEGER_BIT_SIZE) {
956967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore			merged_datum =
95709387b43153953006471dbb06ece6bf779d10937Bob Moore			    raw_datum >> (access_bit_width -
958967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore					  obj_desc->common_field.
959967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore					  start_field_bit_offset);
960967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		} else {
961967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore			merged_datum = 0;
962967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore		}
963967440e3be1af06ad4dc7bb18d2e3c16130fe067Bob Moore
9644c90ece249992c7a2e3fc921e5cdb8eb92193067Bob Moore		mask = width_mask;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i == datum_count) {
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Get the next input datum from the buffer */
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		buffer_offset += obj_desc->common_field.access_byte_width;
9734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
9744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    ACPI_MIN(obj_desc->common_field.access_byte_width,
9754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown				     buffer_length - buffer_offset));
97609387b43153953006471dbb06ece6bf779d10937Bob Moore
9774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		merged_datum |=
9784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		    raw_datum << obj_desc->common_field.start_field_bit_offset;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Mask off any extra bits in the last datum */
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	buffer_tail_bits = (obj_desc->common_field.bit_length +
9844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown			    obj_desc->common_field.start_field_bit_offset) %
98509387b43153953006471dbb06ece6bf779d10937Bob Moore	    access_bit_width;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (buffer_tail_bits) {
9874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write the last datum to the field */
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	merged_datum &= mask;
9934be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	status = acpi_ex_write_with_update_rule(obj_desc,
9944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						mask, merged_datum,
9954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown						field_offset);
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9979aa6169f471771324b476a90d9392daa06d63a2dBob Moore      exit:
9989aa6169f471771324b476a90d9392daa06d63a2dBob Moore	/* Free temporary buffer if we used one */
9999aa6169f471771324b476a90d9392daa06d63a2dBob Moore
10009aa6169f471771324b476a90d9392daa06d63a2dBob Moore	if (new_buffer) {
10019aa6169f471771324b476a90d9392daa06d63a2dBob Moore		ACPI_FREE(new_buffer);
10029aa6169f471771324b476a90d9392daa06d63a2dBob Moore	}
10034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	return_ACPI_STATUS(status);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1005