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 ¤t_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