1*95b482a8SLen Brown 2*95b482a8SLen Brown /****************************************************************************** 3*95b482a8SLen Brown * 4*95b482a8SLen Brown * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities 5*95b482a8SLen Brown * 6*95b482a8SLen Brown *****************************************************************************/ 7*95b482a8SLen Brown 8*95b482a8SLen Brown /* 9*95b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 10*95b482a8SLen Brown * All rights reserved. 11*95b482a8SLen Brown * 12*95b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 13*95b482a8SLen Brown * modification, are permitted provided that the following conditions 14*95b482a8SLen Brown * are met: 15*95b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 16*95b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 17*95b482a8SLen Brown * without modification. 18*95b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19*95b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 20*95b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 21*95b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 22*95b482a8SLen Brown * binary redistribution. 23*95b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 24*95b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 25*95b482a8SLen Brown * from this software without specific prior written permission. 26*95b482a8SLen Brown * 27*95b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 28*95b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 29*95b482a8SLen Brown * Software Foundation. 30*95b482a8SLen Brown * 31*95b482a8SLen Brown * NO WARRANTY 32*95b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*95b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*95b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35*95b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36*95b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37*95b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38*95b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39*95b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40*95b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41*95b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42*95b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 43*95b482a8SLen Brown */ 44*95b482a8SLen Brown 45*95b482a8SLen Brown #include <acpi/acpi.h> 46*95b482a8SLen Brown #include <acpi/accommon.h> 47*95b482a8SLen Brown #include <acpi/acinterp.h> 48*95b482a8SLen Brown #include <acpi/amlcode.h> 49*95b482a8SLen Brown #include <acpi/acnamesp.h> 50*95b482a8SLen Brown 51*95b482a8SLen Brown #define _COMPONENT ACPI_EXECUTER 52*95b482a8SLen Brown ACPI_MODULE_NAME("exprep") 53*95b482a8SLen Brown 54*95b482a8SLen Brown /* Local prototypes */ 55*95b482a8SLen Brown static u32 56*95b482a8SLen Brown acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, 57*95b482a8SLen Brown u8 field_flags, u32 * return_byte_alignment); 58*95b482a8SLen Brown 59*95b482a8SLen Brown #ifdef ACPI_UNDER_DEVELOPMENT 60*95b482a8SLen Brown 61*95b482a8SLen Brown static u32 62*95b482a8SLen Brown acpi_ex_generate_access(u32 field_bit_offset, 63*95b482a8SLen Brown u32 field_bit_length, u32 region_length); 64*95b482a8SLen Brown 65*95b482a8SLen Brown /******************************************************************************* 66*95b482a8SLen Brown * 67*95b482a8SLen Brown * FUNCTION: acpi_ex_generate_access 68*95b482a8SLen Brown * 69*95b482a8SLen Brown * PARAMETERS: field_bit_offset - Start of field within parent region/buffer 70*95b482a8SLen Brown * field_bit_length - Length of field in bits 71*95b482a8SLen Brown * region_length - Length of parent in bytes 72*95b482a8SLen Brown * 73*95b482a8SLen Brown * RETURN: Field granularity (8, 16, 32 or 64) and 74*95b482a8SLen Brown * byte_alignment (1, 2, 3, or 4) 75*95b482a8SLen Brown * 76*95b482a8SLen Brown * DESCRIPTION: Generate an optimal access width for fields defined with the 77*95b482a8SLen Brown * any_acc keyword. 78*95b482a8SLen Brown * 79*95b482a8SLen Brown * NOTE: Need to have the region_length in order to check for boundary 80*95b482a8SLen Brown * conditions (end-of-region). However, the region_length is a deferred 81*95b482a8SLen Brown * operation. Therefore, to complete this implementation, the generation 82*95b482a8SLen Brown * of this access width must be deferred until the region length has 83*95b482a8SLen Brown * been evaluated. 84*95b482a8SLen Brown * 85*95b482a8SLen Brown ******************************************************************************/ 86*95b482a8SLen Brown 87*95b482a8SLen Brown static u32 88*95b482a8SLen Brown acpi_ex_generate_access(u32 field_bit_offset, 89*95b482a8SLen Brown u32 field_bit_length, u32 region_length) 90*95b482a8SLen Brown { 91*95b482a8SLen Brown u32 field_byte_length; 92*95b482a8SLen Brown u32 field_byte_offset; 93*95b482a8SLen Brown u32 field_byte_end_offset; 94*95b482a8SLen Brown u32 access_byte_width; 95*95b482a8SLen Brown u32 field_start_offset; 96*95b482a8SLen Brown u32 field_end_offset; 97*95b482a8SLen Brown u32 minimum_access_width = 0xFFFFFFFF; 98*95b482a8SLen Brown u32 minimum_accesses = 0xFFFFFFFF; 99*95b482a8SLen Brown u32 accesses; 100*95b482a8SLen Brown 101*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_generate_access); 102*95b482a8SLen Brown 103*95b482a8SLen Brown /* Round Field start offset and length to "minimal" byte boundaries */ 104*95b482a8SLen Brown 105*95b482a8SLen Brown field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8)); 106*95b482a8SLen Brown field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length + 107*95b482a8SLen Brown field_bit_offset, 8)); 108*95b482a8SLen Brown field_byte_length = field_byte_end_offset - field_byte_offset; 109*95b482a8SLen Brown 110*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 111*95b482a8SLen Brown "Bit length %d, Bit offset %d\n", 112*95b482a8SLen Brown field_bit_length, field_bit_offset)); 113*95b482a8SLen Brown 114*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 115*95b482a8SLen Brown "Byte Length %d, Byte Offset %d, End Offset %d\n", 116*95b482a8SLen Brown field_byte_length, field_byte_offset, 117*95b482a8SLen Brown field_byte_end_offset)); 118*95b482a8SLen Brown 119*95b482a8SLen Brown /* 120*95b482a8SLen Brown * Iterative search for the maximum access width that is both aligned 121*95b482a8SLen Brown * and does not go beyond the end of the region 122*95b482a8SLen Brown * 123*95b482a8SLen Brown * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes) 124*95b482a8SLen Brown */ 125*95b482a8SLen Brown for (access_byte_width = 1; access_byte_width <= 8; 126*95b482a8SLen Brown access_byte_width <<= 1) { 127*95b482a8SLen Brown /* 128*95b482a8SLen Brown * 1) Round end offset up to next access boundary and make sure that 129*95b482a8SLen Brown * this does not go beyond the end of the parent region. 130*95b482a8SLen Brown * 2) When the Access width is greater than the field_byte_length, we 131*95b482a8SLen Brown * are done. (This does not optimize for the perfectly aligned 132*95b482a8SLen Brown * case yet). 133*95b482a8SLen Brown */ 134*95b482a8SLen Brown if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <= 135*95b482a8SLen Brown region_length) { 136*95b482a8SLen Brown field_start_offset = 137*95b482a8SLen Brown ACPI_ROUND_DOWN(field_byte_offset, 138*95b482a8SLen Brown access_byte_width) / 139*95b482a8SLen Brown access_byte_width; 140*95b482a8SLen Brown 141*95b482a8SLen Brown field_end_offset = 142*95b482a8SLen Brown ACPI_ROUND_UP((field_byte_length + 143*95b482a8SLen Brown field_byte_offset), 144*95b482a8SLen Brown access_byte_width) / 145*95b482a8SLen Brown access_byte_width; 146*95b482a8SLen Brown 147*95b482a8SLen Brown accesses = field_end_offset - field_start_offset; 148*95b482a8SLen Brown 149*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 150*95b482a8SLen Brown "AccessWidth %d end is within region\n", 151*95b482a8SLen Brown access_byte_width)); 152*95b482a8SLen Brown 153*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 154*95b482a8SLen Brown "Field Start %d, Field End %d -- requires %d accesses\n", 155*95b482a8SLen Brown field_start_offset, field_end_offset, 156*95b482a8SLen Brown accesses)); 157*95b482a8SLen Brown 158*95b482a8SLen Brown /* Single access is optimal */ 159*95b482a8SLen Brown 160*95b482a8SLen Brown if (accesses <= 1) { 161*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 162*95b482a8SLen Brown "Entire field can be accessed with one operation of size %d\n", 163*95b482a8SLen Brown access_byte_width)); 164*95b482a8SLen Brown return_VALUE(access_byte_width); 165*95b482a8SLen Brown } 166*95b482a8SLen Brown 167*95b482a8SLen Brown /* 168*95b482a8SLen Brown * Fits in the region, but requires more than one read/write. 169*95b482a8SLen Brown * try the next wider access on next iteration 170*95b482a8SLen Brown */ 171*95b482a8SLen Brown if (accesses < minimum_accesses) { 172*95b482a8SLen Brown minimum_accesses = accesses; 173*95b482a8SLen Brown minimum_access_width = access_byte_width; 174*95b482a8SLen Brown } 175*95b482a8SLen Brown } else { 176*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 177*95b482a8SLen Brown "AccessWidth %d end is NOT within region\n", 178*95b482a8SLen Brown access_byte_width)); 179*95b482a8SLen Brown if (access_byte_width == 1) { 180*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 181*95b482a8SLen Brown "Field goes beyond end-of-region!\n")); 182*95b482a8SLen Brown 183*95b482a8SLen Brown /* Field does not fit in the region at all */ 184*95b482a8SLen Brown 185*95b482a8SLen Brown return_VALUE(0); 186*95b482a8SLen Brown } 187*95b482a8SLen Brown 188*95b482a8SLen Brown /* 189*95b482a8SLen Brown * This width goes beyond the end-of-region, back off to 190*95b482a8SLen Brown * previous access 191*95b482a8SLen Brown */ 192*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 193*95b482a8SLen Brown "Backing off to previous optimal access width of %d\n", 194*95b482a8SLen Brown minimum_access_width)); 195*95b482a8SLen Brown return_VALUE(minimum_access_width); 196*95b482a8SLen Brown } 197*95b482a8SLen Brown } 198*95b482a8SLen Brown 199*95b482a8SLen Brown /* 200*95b482a8SLen Brown * Could not read/write field with one operation, 201*95b482a8SLen Brown * just use max access width 202*95b482a8SLen Brown */ 203*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 204*95b482a8SLen Brown "Cannot access field in one operation, using width 8\n")); 205*95b482a8SLen Brown return_VALUE(8); 206*95b482a8SLen Brown } 207*95b482a8SLen Brown #endif /* ACPI_UNDER_DEVELOPMENT */ 208*95b482a8SLen Brown 209*95b482a8SLen Brown /******************************************************************************* 210*95b482a8SLen Brown * 211*95b482a8SLen Brown * FUNCTION: acpi_ex_decode_field_access 212*95b482a8SLen Brown * 213*95b482a8SLen Brown * PARAMETERS: obj_desc - Field object 214*95b482a8SLen Brown * field_flags - Encoded fieldflags (contains access bits) 215*95b482a8SLen Brown * return_byte_alignment - Where the byte alignment is returned 216*95b482a8SLen Brown * 217*95b482a8SLen Brown * RETURN: Field granularity (8, 16, 32 or 64) and 218*95b482a8SLen Brown * byte_alignment (1, 2, 3, or 4) 219*95b482a8SLen Brown * 220*95b482a8SLen Brown * DESCRIPTION: Decode the access_type bits of a field definition. 221*95b482a8SLen Brown * 222*95b482a8SLen Brown ******************************************************************************/ 223*95b482a8SLen Brown 224*95b482a8SLen Brown static u32 225*95b482a8SLen Brown acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, 226*95b482a8SLen Brown u8 field_flags, u32 * return_byte_alignment) 227*95b482a8SLen Brown { 228*95b482a8SLen Brown u32 access; 229*95b482a8SLen Brown u32 byte_alignment; 230*95b482a8SLen Brown u32 bit_length; 231*95b482a8SLen Brown 232*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_decode_field_access); 233*95b482a8SLen Brown 234*95b482a8SLen Brown access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); 235*95b482a8SLen Brown 236*95b482a8SLen Brown switch (access) { 237*95b482a8SLen Brown case AML_FIELD_ACCESS_ANY: 238*95b482a8SLen Brown 239*95b482a8SLen Brown #ifdef ACPI_UNDER_DEVELOPMENT 240*95b482a8SLen Brown byte_alignment = 241*95b482a8SLen Brown acpi_ex_generate_access(obj_desc->common_field. 242*95b482a8SLen Brown start_field_bit_offset, 243*95b482a8SLen Brown obj_desc->common_field.bit_length, 244*95b482a8SLen Brown 0xFFFFFFFF 245*95b482a8SLen Brown /* Temp until we pass region_length as parameter */ 246*95b482a8SLen Brown ); 247*95b482a8SLen Brown bit_length = byte_alignment * 8; 248*95b482a8SLen Brown #endif 249*95b482a8SLen Brown 250*95b482a8SLen Brown byte_alignment = 1; 251*95b482a8SLen Brown bit_length = 8; 252*95b482a8SLen Brown break; 253*95b482a8SLen Brown 254*95b482a8SLen Brown case AML_FIELD_ACCESS_BYTE: 255*95b482a8SLen Brown case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ 256*95b482a8SLen Brown byte_alignment = 1; 257*95b482a8SLen Brown bit_length = 8; 258*95b482a8SLen Brown break; 259*95b482a8SLen Brown 260*95b482a8SLen Brown case AML_FIELD_ACCESS_WORD: 261*95b482a8SLen Brown byte_alignment = 2; 262*95b482a8SLen Brown bit_length = 16; 263*95b482a8SLen Brown break; 264*95b482a8SLen Brown 265*95b482a8SLen Brown case AML_FIELD_ACCESS_DWORD: 266*95b482a8SLen Brown byte_alignment = 4; 267*95b482a8SLen Brown bit_length = 32; 268*95b482a8SLen Brown break; 269*95b482a8SLen Brown 270*95b482a8SLen Brown case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ 271*95b482a8SLen Brown byte_alignment = 8; 272*95b482a8SLen Brown bit_length = 64; 273*95b482a8SLen Brown break; 274*95b482a8SLen Brown 275*95b482a8SLen Brown default: 276*95b482a8SLen Brown /* Invalid field access type */ 277*95b482a8SLen Brown 278*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "Unknown field access type %X", access)); 279*95b482a8SLen Brown return_UINT32(0); 280*95b482a8SLen Brown } 281*95b482a8SLen Brown 282*95b482a8SLen Brown if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { 283*95b482a8SLen Brown /* 284*95b482a8SLen Brown * buffer_field access can be on any byte boundary, so the 285*95b482a8SLen Brown * byte_alignment is always 1 byte -- regardless of any byte_alignment 286*95b482a8SLen Brown * implied by the field access type. 287*95b482a8SLen Brown */ 288*95b482a8SLen Brown byte_alignment = 1; 289*95b482a8SLen Brown } 290*95b482a8SLen Brown 291*95b482a8SLen Brown *return_byte_alignment = byte_alignment; 292*95b482a8SLen Brown return_UINT32(bit_length); 293*95b482a8SLen Brown } 294*95b482a8SLen Brown 295*95b482a8SLen Brown /******************************************************************************* 296*95b482a8SLen Brown * 297*95b482a8SLen Brown * FUNCTION: acpi_ex_prep_common_field_object 298*95b482a8SLen Brown * 299*95b482a8SLen Brown * PARAMETERS: obj_desc - The field object 300*95b482a8SLen Brown * field_flags - Access, lock_rule, and update_rule. 301*95b482a8SLen Brown * The format of a field_flag is described 302*95b482a8SLen Brown * in the ACPI specification 303*95b482a8SLen Brown * field_attribute - Special attributes (not used) 304*95b482a8SLen Brown * field_bit_position - Field start position 305*95b482a8SLen Brown * field_bit_length - Field length in number of bits 306*95b482a8SLen Brown * 307*95b482a8SLen Brown * RETURN: Status 308*95b482a8SLen Brown * 309*95b482a8SLen Brown * DESCRIPTION: Initialize the areas of the field object that are common 310*95b482a8SLen Brown * to the various types of fields. Note: This is very "sensitive" 311*95b482a8SLen Brown * code because we are solving the general case for field 312*95b482a8SLen Brown * alignment. 313*95b482a8SLen Brown * 314*95b482a8SLen Brown ******************************************************************************/ 315*95b482a8SLen Brown 316*95b482a8SLen Brown acpi_status 317*95b482a8SLen Brown acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, 318*95b482a8SLen Brown u8 field_flags, 319*95b482a8SLen Brown u8 field_attribute, 320*95b482a8SLen Brown u32 field_bit_position, u32 field_bit_length) 321*95b482a8SLen Brown { 322*95b482a8SLen Brown u32 access_bit_width; 323*95b482a8SLen Brown u32 byte_alignment; 324*95b482a8SLen Brown u32 nearest_byte_address; 325*95b482a8SLen Brown 326*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_prep_common_field_object); 327*95b482a8SLen Brown 328*95b482a8SLen Brown /* 329*95b482a8SLen Brown * Note: the structure being initialized is the 330*95b482a8SLen Brown * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common 331*95b482a8SLen Brown * area are initialized by this procedure. 332*95b482a8SLen Brown */ 333*95b482a8SLen Brown obj_desc->common_field.field_flags = field_flags; 334*95b482a8SLen Brown obj_desc->common_field.attribute = field_attribute; 335*95b482a8SLen Brown obj_desc->common_field.bit_length = field_bit_length; 336*95b482a8SLen Brown 337*95b482a8SLen Brown /* 338*95b482a8SLen Brown * Decode the access type so we can compute offsets. The access type gives 339*95b482a8SLen Brown * two pieces of information - the width of each field access and the 340*95b482a8SLen Brown * necessary byte_alignment (address granularity) of the access. 341*95b482a8SLen Brown * 342*95b482a8SLen Brown * For any_acc, the access_bit_width is the largest width that is both 343*95b482a8SLen Brown * necessary and possible in an attempt to access the whole field in one 344*95b482a8SLen Brown * I/O operation. However, for any_acc, the byte_alignment is always one 345*95b482a8SLen Brown * byte. 346*95b482a8SLen Brown * 347*95b482a8SLen Brown * For all Buffer Fields, the byte_alignment is always one byte. 348*95b482a8SLen Brown * 349*95b482a8SLen Brown * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is 350*95b482a8SLen Brown * the same (equivalent) as the byte_alignment. 351*95b482a8SLen Brown */ 352*95b482a8SLen Brown access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags, 353*95b482a8SLen Brown &byte_alignment); 354*95b482a8SLen Brown if (!access_bit_width) { 355*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 356*95b482a8SLen Brown } 357*95b482a8SLen Brown 358*95b482a8SLen Brown /* Setup width (access granularity) fields */ 359*95b482a8SLen Brown 360*95b482a8SLen Brown obj_desc->common_field.access_byte_width = (u8) 361*95b482a8SLen Brown ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */ 362*95b482a8SLen Brown 363*95b482a8SLen Brown obj_desc->common_field.access_bit_width = (u8) access_bit_width; 364*95b482a8SLen Brown 365*95b482a8SLen Brown /* 366*95b482a8SLen Brown * base_byte_offset is the address of the start of the field within the 367*95b482a8SLen Brown * region. It is the byte address of the first *datum* (field-width data 368*95b482a8SLen Brown * unit) of the field. (i.e., the first datum that contains at least the 369*95b482a8SLen Brown * first *bit* of the field.) 370*95b482a8SLen Brown * 371*95b482a8SLen Brown * Note: byte_alignment is always either equal to the access_bit_width or 8 372*95b482a8SLen Brown * (Byte access), and it defines the addressing granularity of the parent 373*95b482a8SLen Brown * region or buffer. 374*95b482a8SLen Brown */ 375*95b482a8SLen Brown nearest_byte_address = 376*95b482a8SLen Brown ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position); 377*95b482a8SLen Brown obj_desc->common_field.base_byte_offset = (u32) 378*95b482a8SLen Brown ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment); 379*95b482a8SLen Brown 380*95b482a8SLen Brown /* 381*95b482a8SLen Brown * start_field_bit_offset is the offset of the first bit of the field within 382*95b482a8SLen Brown * a field datum. 383*95b482a8SLen Brown */ 384*95b482a8SLen Brown obj_desc->common_field.start_field_bit_offset = (u8) 385*95b482a8SLen Brown (field_bit_position - 386*95b482a8SLen Brown ACPI_MUL_8(obj_desc->common_field.base_byte_offset)); 387*95b482a8SLen Brown 388*95b482a8SLen Brown /* 389*95b482a8SLen Brown * Does the entire field fit within a single field access element? (datum) 390*95b482a8SLen Brown * (i.e., without crossing a datum boundary) 391*95b482a8SLen Brown */ 392*95b482a8SLen Brown if ((obj_desc->common_field.start_field_bit_offset + 393*95b482a8SLen Brown field_bit_length) <= (u16) access_bit_width) { 394*95b482a8SLen Brown obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM; 395*95b482a8SLen Brown } 396*95b482a8SLen Brown 397*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 398*95b482a8SLen Brown } 399*95b482a8SLen Brown 400*95b482a8SLen Brown /******************************************************************************* 401*95b482a8SLen Brown * 402*95b482a8SLen Brown * FUNCTION: acpi_ex_prep_field_value 403*95b482a8SLen Brown * 404*95b482a8SLen Brown * PARAMETERS: Info - Contains all field creation info 405*95b482a8SLen Brown * 406*95b482a8SLen Brown * RETURN: Status 407*95b482a8SLen Brown * 408*95b482a8SLen Brown * DESCRIPTION: Construct an union acpi_operand_object of type def_field and 409*95b482a8SLen Brown * connect it to the parent Node. 410*95b482a8SLen Brown * 411*95b482a8SLen Brown ******************************************************************************/ 412*95b482a8SLen Brown 413*95b482a8SLen Brown acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) 414*95b482a8SLen Brown { 415*95b482a8SLen Brown union acpi_operand_object *obj_desc; 416*95b482a8SLen Brown union acpi_operand_object *second_desc = NULL; 417*95b482a8SLen Brown u32 type; 418*95b482a8SLen Brown acpi_status status; 419*95b482a8SLen Brown 420*95b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_prep_field_value); 421*95b482a8SLen Brown 422*95b482a8SLen Brown /* Parameter validation */ 423*95b482a8SLen Brown 424*95b482a8SLen Brown if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { 425*95b482a8SLen Brown if (!info->region_node) { 426*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "Null RegionNode")); 427*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_NO_OPERAND); 428*95b482a8SLen Brown } 429*95b482a8SLen Brown 430*95b482a8SLen Brown type = acpi_ns_get_type(info->region_node); 431*95b482a8SLen Brown if (type != ACPI_TYPE_REGION) { 432*95b482a8SLen Brown ACPI_ERROR((AE_INFO, 433*95b482a8SLen Brown "Needed Region, found type %X (%s)", 434*95b482a8SLen Brown type, acpi_ut_get_type_name(type))); 435*95b482a8SLen Brown 436*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 437*95b482a8SLen Brown } 438*95b482a8SLen Brown } 439*95b482a8SLen Brown 440*95b482a8SLen Brown /* Allocate a new field object */ 441*95b482a8SLen Brown 442*95b482a8SLen Brown obj_desc = acpi_ut_create_internal_object(info->field_type); 443*95b482a8SLen Brown if (!obj_desc) { 444*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 445*95b482a8SLen Brown } 446*95b482a8SLen Brown 447*95b482a8SLen Brown /* Initialize areas of the object that are common to all fields */ 448*95b482a8SLen Brown 449*95b482a8SLen Brown obj_desc->common_field.node = info->field_node; 450*95b482a8SLen Brown status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, 451*95b482a8SLen Brown info->attribute, 452*95b482a8SLen Brown info->field_bit_position, 453*95b482a8SLen Brown info->field_bit_length); 454*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 455*95b482a8SLen Brown acpi_ut_delete_object_desc(obj_desc); 456*95b482a8SLen Brown return_ACPI_STATUS(status); 457*95b482a8SLen Brown } 458*95b482a8SLen Brown 459*95b482a8SLen Brown /* Initialize areas of the object that are specific to the field type */ 460*95b482a8SLen Brown 461*95b482a8SLen Brown switch (info->field_type) { 462*95b482a8SLen Brown case ACPI_TYPE_LOCAL_REGION_FIELD: 463*95b482a8SLen Brown 464*95b482a8SLen Brown obj_desc->field.region_obj = 465*95b482a8SLen Brown acpi_ns_get_attached_object(info->region_node); 466*95b482a8SLen Brown 467*95b482a8SLen Brown /* An additional reference for the container */ 468*95b482a8SLen Brown 469*95b482a8SLen Brown acpi_ut_add_reference(obj_desc->field.region_obj); 470*95b482a8SLen Brown 471*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 472*95b482a8SLen Brown "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", 473*95b482a8SLen Brown obj_desc->field.start_field_bit_offset, 474*95b482a8SLen Brown obj_desc->field.base_byte_offset, 475*95b482a8SLen Brown obj_desc->field.access_byte_width, 476*95b482a8SLen Brown obj_desc->field.region_obj)); 477*95b482a8SLen Brown break; 478*95b482a8SLen Brown 479*95b482a8SLen Brown case ACPI_TYPE_LOCAL_BANK_FIELD: 480*95b482a8SLen Brown 481*95b482a8SLen Brown obj_desc->bank_field.value = info->bank_value; 482*95b482a8SLen Brown obj_desc->bank_field.region_obj = 483*95b482a8SLen Brown acpi_ns_get_attached_object(info->region_node); 484*95b482a8SLen Brown obj_desc->bank_field.bank_obj = 485*95b482a8SLen Brown acpi_ns_get_attached_object(info->register_node); 486*95b482a8SLen Brown 487*95b482a8SLen Brown /* An additional reference for the attached objects */ 488*95b482a8SLen Brown 489*95b482a8SLen Brown acpi_ut_add_reference(obj_desc->bank_field.region_obj); 490*95b482a8SLen Brown acpi_ut_add_reference(obj_desc->bank_field.bank_obj); 491*95b482a8SLen Brown 492*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 493*95b482a8SLen Brown "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", 494*95b482a8SLen Brown obj_desc->bank_field.start_field_bit_offset, 495*95b482a8SLen Brown obj_desc->bank_field.base_byte_offset, 496*95b482a8SLen Brown obj_desc->field.access_byte_width, 497*95b482a8SLen Brown obj_desc->bank_field.region_obj, 498*95b482a8SLen Brown obj_desc->bank_field.bank_obj)); 499*95b482a8SLen Brown 500*95b482a8SLen Brown /* 501*95b482a8SLen Brown * Remember location in AML stream of the field unit 502*95b482a8SLen Brown * opcode and operands -- since the bank_value 503*95b482a8SLen Brown * operands must be evaluated. 504*95b482a8SLen Brown */ 505*95b482a8SLen Brown second_desc = obj_desc->common.next_object; 506*95b482a8SLen Brown second_desc->extra.aml_start = 507*95b482a8SLen Brown ACPI_CAST_PTR(union acpi_parse_object, 508*95b482a8SLen Brown info->data_register_node)->named.data; 509*95b482a8SLen Brown second_desc->extra.aml_length = 510*95b482a8SLen Brown ACPI_CAST_PTR(union acpi_parse_object, 511*95b482a8SLen Brown info->data_register_node)->named.length; 512*95b482a8SLen Brown 513*95b482a8SLen Brown break; 514*95b482a8SLen Brown 515*95b482a8SLen Brown case ACPI_TYPE_LOCAL_INDEX_FIELD: 516*95b482a8SLen Brown 517*95b482a8SLen Brown /* Get the Index and Data registers */ 518*95b482a8SLen Brown 519*95b482a8SLen Brown obj_desc->index_field.index_obj = 520*95b482a8SLen Brown acpi_ns_get_attached_object(info->register_node); 521*95b482a8SLen Brown obj_desc->index_field.data_obj = 522*95b482a8SLen Brown acpi_ns_get_attached_object(info->data_register_node); 523*95b482a8SLen Brown 524*95b482a8SLen Brown if (!obj_desc->index_field.data_obj 525*95b482a8SLen Brown || !obj_desc->index_field.index_obj) { 526*95b482a8SLen Brown ACPI_ERROR((AE_INFO, 527*95b482a8SLen Brown "Null Index Object during field prep")); 528*95b482a8SLen Brown acpi_ut_delete_object_desc(obj_desc); 529*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_INTERNAL); 530*95b482a8SLen Brown } 531*95b482a8SLen Brown 532*95b482a8SLen Brown /* An additional reference for the attached objects */ 533*95b482a8SLen Brown 534*95b482a8SLen Brown acpi_ut_add_reference(obj_desc->index_field.data_obj); 535*95b482a8SLen Brown acpi_ut_add_reference(obj_desc->index_field.index_obj); 536*95b482a8SLen Brown 537*95b482a8SLen Brown /* 538*95b482a8SLen Brown * April 2006: Changed to match MS behavior 539*95b482a8SLen Brown * 540*95b482a8SLen Brown * The value written to the Index register is the byte offset of the 541*95b482a8SLen Brown * target field in units of the granularity of the index_field 542*95b482a8SLen Brown * 543*95b482a8SLen Brown * Previously, the value was calculated as an index in terms of the 544*95b482a8SLen Brown * width of the Data register, as below: 545*95b482a8SLen Brown * 546*95b482a8SLen Brown * obj_desc->index_field.Value = (u32) 547*95b482a8SLen Brown * (Info->field_bit_position / ACPI_MUL_8 ( 548*95b482a8SLen Brown * obj_desc->Field.access_byte_width)); 549*95b482a8SLen Brown * 550*95b482a8SLen Brown * February 2006: Tried value as a byte offset: 551*95b482a8SLen Brown * obj_desc->index_field.Value = (u32) 552*95b482a8SLen Brown * ACPI_DIV_8 (Info->field_bit_position); 553*95b482a8SLen Brown */ 554*95b482a8SLen Brown obj_desc->index_field.value = 555*95b482a8SLen Brown (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), 556*95b482a8SLen Brown obj_desc->index_field. 557*95b482a8SLen Brown access_byte_width); 558*95b482a8SLen Brown 559*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 560*95b482a8SLen Brown "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", 561*95b482a8SLen Brown obj_desc->index_field.start_field_bit_offset, 562*95b482a8SLen Brown obj_desc->index_field.base_byte_offset, 563*95b482a8SLen Brown obj_desc->index_field.value, 564*95b482a8SLen Brown obj_desc->field.access_byte_width, 565*95b482a8SLen Brown obj_desc->index_field.index_obj, 566*95b482a8SLen Brown obj_desc->index_field.data_obj)); 567*95b482a8SLen Brown break; 568*95b482a8SLen Brown 569*95b482a8SLen Brown default: 570*95b482a8SLen Brown /* No other types should get here */ 571*95b482a8SLen Brown break; 572*95b482a8SLen Brown } 573*95b482a8SLen Brown 574*95b482a8SLen Brown /* 575*95b482a8SLen Brown * Store the constructed descriptor (obj_desc) into the parent Node, 576*95b482a8SLen Brown * preserving the current type of that named_obj. 577*95b482a8SLen Brown */ 578*95b482a8SLen Brown status = acpi_ns_attach_object(info->field_node, obj_desc, 579*95b482a8SLen Brown acpi_ns_get_type(info->field_node)); 580*95b482a8SLen Brown 581*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 582*95b482a8SLen Brown "Set NamedObj %p [%4.4s], ObjDesc %p\n", 583*95b482a8SLen Brown info->field_node, 584*95b482a8SLen Brown acpi_ut_get_node_name(info->field_node), obj_desc)); 585*95b482a8SLen Brown 586*95b482a8SLen Brown /* Remove local reference to the object */ 587*95b482a8SLen Brown 588*95b482a8SLen Brown acpi_ut_remove_reference(obj_desc); 589*95b482a8SLen Brown return_ACPI_STATUS(status); 590*95b482a8SLen Brown } 591