exfldio.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:27k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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