exfldio.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. /******************************************************************************
  2. *
  3. * Module Name: exfldio - Aml Field I/O
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2005, R. Byron Moore
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include <acpi/acpi.h>
  43. #include <acpi/acinterp.h>
  44. #include <acpi/amlcode.h>
  45. #include <acpi/acevents.h>
  46. #include <acpi/acdispat.h>
  47. #define _COMPONENT ACPI_EXECUTER
  48. ACPI_MODULE_NAME ("exfldio")
  49. /*******************************************************************************
  50. *
  51. * FUNCTION: acpi_ex_setup_region
  52. *
  53. * PARAMETERS: *obj_desc - Field to be read or written
  54. * field_datum_byte_offset - Byte offset of this datum within the
  55. * parent field
  56. *
  57. * RETURN: Status
  58. *
  59. * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
  60. * acpi_ex_insert_into_field. Initialize the Region if necessary and
  61. * validate the request.
  62. *
  63. ******************************************************************************/
  64. acpi_status
  65. acpi_ex_setup_region (
  66. union acpi_operand_object *obj_desc,
  67. u32 field_datum_byte_offset)
  68. {
  69. acpi_status status = AE_OK;
  70. union acpi_operand_object *rgn_desc;
  71. ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);
  72. rgn_desc = obj_desc->common_field.region_obj;
  73. /* We must have a valid region */
  74. if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
  75. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
  76. ACPI_GET_OBJECT_TYPE (rgn_desc),
  77. acpi_ut_get_object_type_name (rgn_desc)));
  78. return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
  79. }
  80. /*
  81. * If the Region Address and Length have not been previously evaluated,
  82. * evaluate them now and save the results.
  83. */
  84. if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
  85. status = acpi_ds_get_region_arguments (rgn_desc);
  86. if (ACPI_FAILURE (status)) {
  87. return_ACPI_STATUS (status);
  88. }
  89. }
  90. if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
  91. /* SMBus has a non-linear address space */
  92. return_ACPI_STATUS (AE_OK);
  93. }
  94. #ifdef ACPI_UNDER_DEVELOPMENT
  95. /*
  96. * If the Field access is any_acc, we can now compute the optimal
  97. * access (because we know know the length of the parent region)
  98. */
  99. if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
  100. if (ACPI_FAILURE (status)) {
  101. return_ACPI_STATUS (status);
  102. }
  103. }
  104. #endif
  105. /*
  106. * Validate the request. The entire request from the byte offset for a
  107. * length of one field datum (access width) must fit within the region.
  108. * (Region length is specified in bytes)
  109. */
  110. if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
  111. + field_datum_byte_offset
  112. + obj_desc->common_field.access_byte_width)) {
  113. if (acpi_gbl_enable_interpreter_slack) {
  114. /*
  115. * Slack mode only: We will go ahead and allow access to this
  116. * field if it is within the region length rounded up to the next
  117. * access width boundary.
  118. */
  119. if (ACPI_ROUND_UP (rgn_desc->region.length,
  120. obj_desc->common_field.access_byte_width) >=
  121. (obj_desc->common_field.base_byte_offset +
  122. (acpi_native_uint) obj_desc->common_field.access_byte_width +
  123. field_datum_byte_offset)) {
  124. return_ACPI_STATUS (AE_OK);
  125. }
  126. }
  127. if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
  128. /*
  129. * This is the case where the access_type (acc_word, etc.) is wider
  130. * than the region itself. For example, a region of length one
  131. * byte, and a field with Dword access specified.
  132. */
  133. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  134. "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
  135. acpi_ut_get_node_name (obj_desc->common_field.node),
  136. obj_desc->common_field.access_byte_width,
  137. acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
  138. }
  139. /*
  140. * Offset rounded up to next multiple of field width
  141. * exceeds region length, indicate an error
  142. */
  143. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  144. "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
  145. acpi_ut_get_node_name (obj_desc->common_field.node),
  146. obj_desc->common_field.base_byte_offset,
  147. field_datum_byte_offset, obj_desc->common_field.access_byte_width,
  148. acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
  149. return_ACPI_STATUS (AE_AML_REGION_LIMIT);
  150. }
  151. return_ACPI_STATUS (AE_OK);
  152. }
  153. /*******************************************************************************
  154. *
  155. * FUNCTION: acpi_ex_access_region
  156. *
  157. * PARAMETERS: *obj_desc - Field to be read
  158. * field_datum_byte_offset - Byte offset of this datum within the
  159. * parent field
  160. * *Value - Where to store value (must at least
  161. * the size of acpi_integer)
  162. * Function - Read or Write flag plus other region-
  163. * dependent flags
  164. *
  165. * RETURN: Status
  166. *
  167. * DESCRIPTION: Read or Write a single field datum to an Operation Region.
  168. *
  169. ******************************************************************************/
  170. acpi_status
  171. acpi_ex_access_region (
  172. union acpi_operand_object *obj_desc,
  173. u32 field_datum_byte_offset,
  174. acpi_integer *value,
  175. u32 function)
  176. {
  177. acpi_status status;
  178. union acpi_operand_object *rgn_desc;
  179. acpi_physical_address address;
  180. ACPI_FUNCTION_TRACE ("ex_access_region");
  181. /*
  182. * Ensure that the region operands are fully evaluated and verify
  183. * the validity of the request
  184. */
  185. status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
  186. if (ACPI_FAILURE (status)) {
  187. return_ACPI_STATUS (status);
  188. }
  189. /*
  190. * The physical address of this field datum is:
  191. *
  192. * 1) The base of the region, plus
  193. * 2) The base offset of the field, plus
  194. * 3) The current offset into the field
  195. */
  196. rgn_desc = obj_desc->common_field.region_obj;
  197. address = rgn_desc->region.address
  198. + obj_desc->common_field.base_byte_offset
  199. + field_datum_byte_offset;
  200. if ((function & ACPI_IO_MASK) == ACPI_READ) {
  201. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
  202. }
  203. else {
  204. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
  205. }
  206. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
  207. " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
  208. acpi_ut_get_region_name (rgn_desc->region.space_id),
  209. rgn_desc->region.space_id,
  210. obj_desc->common_field.access_byte_width,
  211. obj_desc->common_field.base_byte_offset,
  212. field_datum_byte_offset,
  213. ACPI_FORMAT_UINT64 (address)));
  214. /* Invoke the appropriate address_space/op_region handler */
  215. status = acpi_ev_address_space_dispatch (rgn_desc, function,
  216. address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);
  217. if (ACPI_FAILURE (status)) {
  218. if (status == AE_NOT_IMPLEMENTED) {
  219. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  220. "Region %s(%X) not implemented\n",
  221. acpi_ut_get_region_name (rgn_desc->region.space_id),
  222. rgn_desc->region.space_id));
  223. }
  224. else if (status == AE_NOT_EXIST) {
  225. ACPI_REPORT_ERROR ((
  226. "Region %s(%X) has no handler\n",
  227. acpi_ut_get_region_name (rgn_desc->region.space_id),
  228. rgn_desc->region.space_id));
  229. }
  230. }
  231. return_ACPI_STATUS (status);
  232. }
  233. /*******************************************************************************
  234. *
  235. * FUNCTION: acpi_ex_register_overflow
  236. *
  237. * PARAMETERS: *obj_desc - Register(Field) to be written
  238. * Value - Value to be stored
  239. *
  240. * RETURN: TRUE if value overflows the field, FALSE otherwise
  241. *
  242. * DESCRIPTION: Check if a value is out of range of the field being written.
  243. * Used to check if the values written to Index and Bank registers
  244. * are out of range. Normally, the value is simply truncated
  245. * to fit the field, but this case is most likely a serious
  246. * coding error in the ASL.
  247. *
  248. ******************************************************************************/
  249. u8
  250. acpi_ex_register_overflow (
  251. union acpi_operand_object *obj_desc,
  252. acpi_integer value)
  253. {
  254. if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
  255. /*
  256. * The field is large enough to hold the maximum integer, so we can
  257. * never overflow it.
  258. */
  259. return (FALSE);
  260. }
  261. if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) {
  262. /*
  263. * The Value is larger than the maximum value that can fit into
  264. * the register.
  265. */
  266. return (TRUE);
  267. }
  268. /* The Value will fit into the field with no truncation */
  269. return (FALSE);
  270. }
  271. /*******************************************************************************
  272. *
  273. * FUNCTION: acpi_ex_field_datum_io
  274. *
  275. * PARAMETERS: *obj_desc - Field to be read
  276. * field_datum_byte_offset - Byte offset of this datum within the
  277. * parent field
  278. * *Value - Where to store value (must be 64 bits)
  279. * read_write - Read or Write flag
  280. *
  281. * RETURN: Status
  282. *
  283. * DESCRIPTION: Read or Write a single datum of a field. The field_type is
  284. * demultiplexed here to handle the different types of fields
  285. * (buffer_field, region_field, index_field, bank_field)
  286. *
  287. ******************************************************************************/
  288. acpi_status
  289. acpi_ex_field_datum_io (
  290. union acpi_operand_object *obj_desc,
  291. u32 field_datum_byte_offset,
  292. acpi_integer *value,
  293. u32 read_write)
  294. {
  295. acpi_status status;
  296. acpi_integer local_value;
  297. ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);
  298. if (read_write == ACPI_READ) {
  299. if (!value) {
  300. local_value = 0;
  301. value = &local_value; /* To support reads without saving return value */
  302. }
  303. /* Clear the entire return buffer first, [Very Important!] */
  304. *value = 0;
  305. }
  306. /*
  307. * The four types of fields are:
  308. *
  309. * buffer_field - Read/write from/to a Buffer
  310. * region_field - Read/write from/to a Operation Region.
  311. * bank_field - Write to a Bank Register, then read/write from/to an op_region
  312. * index_field - Write to an Index Register, then read/write from/to a Data Register
  313. */
  314. switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
  315. case ACPI_TYPE_BUFFER_FIELD:
  316. /*
  317. * If the buffer_field arguments have not been previously evaluated,
  318. * evaluate them now and save the results.
  319. */
  320. if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
  321. status = acpi_ds_get_buffer_field_arguments (obj_desc);
  322. if (ACPI_FAILURE (status)) {
  323. return_ACPI_STATUS (status);
  324. }
  325. }
  326. if (read_write == ACPI_READ) {
  327. /*
  328. * Copy the data from the source buffer.
  329. * Length is the field width in bytes.
  330. */
  331. ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer
  332. + obj_desc->buffer_field.base_byte_offset
  333. + field_datum_byte_offset,
  334. obj_desc->common_field.access_byte_width);
  335. }
  336. else {
  337. /*
  338. * Copy the data to the target buffer.
  339. * Length is the field width in bytes.
  340. */
  341. ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer
  342. + obj_desc->buffer_field.base_byte_offset
  343. + field_datum_byte_offset,
  344. value, obj_desc->common_field.access_byte_width);
  345. }
  346. status = AE_OK;
  347. break;
  348. case ACPI_TYPE_LOCAL_BANK_FIELD:
  349. /* Ensure that the bank_value is not beyond the capacity of the register */
  350. if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,
  351. (acpi_integer) obj_desc->bank_field.value)) {
  352. return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
  353. }
  354. /*
  355. * For bank_fields, we must write the bank_value to the bank_register
  356. * (itself a region_field) before we can access the data.
  357. */
  358. status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj,
  359. &obj_desc->bank_field.value,
  360. sizeof (obj_desc->bank_field.value));
  361. if (ACPI_FAILURE (status)) {
  362. return_ACPI_STATUS (status);
  363. }
  364. /*
  365. * Now that the Bank has been selected, fall through to the
  366. * region_field case and write the datum to the Operation Region
  367. */
  368. /*lint -fallthrough */
  369. case ACPI_TYPE_LOCAL_REGION_FIELD:
  370. /*
  371. * For simple region_fields, we just directly access the owning
  372. * Operation Region.
  373. */
  374. status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
  375. read_write);
  376. break;
  377. case ACPI_TYPE_LOCAL_INDEX_FIELD:
  378. /* Ensure that the index_value is not beyond the capacity of the register */
  379. if (acpi_ex_register_overflow (obj_desc->index_field.index_obj,
  380. (acpi_integer) obj_desc->index_field.value)) {
  381. return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
  382. }
  383. /* Write the index value to the index_register (itself a region_field) */
  384. field_datum_byte_offset += obj_desc->index_field.value;
  385. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  386. "Write to Index Register: Value %8.8X\n",
  387. field_datum_byte_offset));
  388. status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj,
  389. &field_datum_byte_offset,
  390. sizeof (field_datum_byte_offset));
  391. if (ACPI_FAILURE (status)) {
  392. return_ACPI_STATUS (status);
  393. }
  394. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  395. "I/O to Data Register: value_ptr %p\n",
  396. value));
  397. if (read_write == ACPI_READ) {
  398. /* Read the datum from the data_register */
  399. status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj,
  400. value, sizeof (acpi_integer));
  401. }
  402. else {
  403. /* Write the datum to the data_register */
  404. status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj,
  405. value, sizeof (acpi_integer));
  406. }
  407. break;
  408. default:
  409. ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
  410. ACPI_GET_OBJECT_TYPE (obj_desc)));
  411. status = AE_AML_INTERNAL;
  412. break;
  413. }
  414. if (ACPI_SUCCESS (status)) {
  415. if (read_write == ACPI_READ) {
  416. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n",
  417. ACPI_FORMAT_UINT64 (*value),
  418. obj_desc->common_field.access_byte_width));
  419. }
  420. else {
  421. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n",
  422. ACPI_FORMAT_UINT64 (*value),
  423. obj_desc->common_field.access_byte_width));
  424. }
  425. }
  426. return_ACPI_STATUS (status);
  427. }
  428. /*******************************************************************************
  429. *
  430. * FUNCTION: acpi_ex_write_with_update_rule
  431. *
  432. * PARAMETERS: *obj_desc - Field to be set
  433. * Value - Value to store
  434. *
  435. * RETURN: Status
  436. *
  437. * DESCRIPTION: Apply the field update rule to a field write
  438. *
  439. ******************************************************************************/
  440. acpi_status
  441. acpi_ex_write_with_update_rule (
  442. union acpi_operand_object *obj_desc,
  443. acpi_integer mask,
  444. acpi_integer field_value,
  445. u32 field_datum_byte_offset)
  446. {
  447. acpi_status status = AE_OK;
  448. acpi_integer merged_value;
  449. acpi_integer current_value;
  450. ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);
  451. /* Start with the new bits */
  452. merged_value = field_value;
  453. /* If the mask is all ones, we don't need to worry about the update rule */
  454. if (mask != ACPI_INTEGER_MAX) {
  455. /* Decode the update rule */
  456. switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
  457. case AML_FIELD_UPDATE_PRESERVE:
  458. /*
  459. * Check if update rule needs to be applied (not if mask is all
  460. * ones) The left shift drops the bits we want to ignore.
  461. */
  462. if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
  463. ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
  464. /*
  465. * Read the current contents of the byte/word/dword containing
  466. * the field, and merge with the new field value.
  467. */
  468. status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
  469. &current_value, ACPI_READ);
  470. if (ACPI_FAILURE (status)) {
  471. return_ACPI_STATUS (status);
  472. }
  473. merged_value |= (current_value & ~mask);
  474. }
  475. break;
  476. case AML_FIELD_UPDATE_WRITE_AS_ONES:
  477. /* Set positions outside the field to all ones */
  478. merged_value |= ~mask;
  479. break;
  480. case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
  481. /* Set positions outside the field to all zeros */
  482. merged_value &= mask;
  483. break;
  484. default:
  485. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  486. "write_with_update_rule: Unknown update_rule setting: %X\n",
  487. (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
  488. return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
  489. }
  490. }
  491. ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  492. "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
  493. ACPI_FORMAT_UINT64 (mask),
  494. field_datum_byte_offset,
  495. obj_desc->common_field.access_byte_width,
  496. ACPI_FORMAT_UINT64 (field_value),
  497. ACPI_FORMAT_UINT64 (merged_value)));
  498. /* Write the merged value */
  499. status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
  500. &merged_value, ACPI_WRITE);
  501. return_ACPI_STATUS (status);
  502. }
  503. /*******************************************************************************
  504. *
  505. * FUNCTION: acpi_ex_extract_from_field
  506. *
  507. * PARAMETERS: obj_desc - Field to be read
  508. * Buffer - Where to store the field data
  509. * buffer_length - Length of Buffer
  510. *
  511. * RETURN: Status
  512. *
  513. * DESCRIPTION: Retrieve the current value of the given field
  514. *
  515. ******************************************************************************/
  516. acpi_status
  517. acpi_ex_extract_from_field (
  518. union acpi_operand_object *obj_desc,
  519. void *buffer,
  520. u32 buffer_length)
  521. {
  522. acpi_status status;
  523. acpi_integer raw_datum;
  524. acpi_integer merged_datum;
  525. u32 field_offset = 0;
  526. u32 buffer_offset = 0;
  527. u32 buffer_tail_bits;
  528. u32 datum_count;
  529. u32 field_datum_count;
  530. u32 i;
  531. ACPI_FUNCTION_TRACE ("ex_extract_from_field");
  532. /* Validate target buffer and clear it */
  533. if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
  534. obj_desc->common_field.bit_length)) {
  535. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  536. "Field size %X (bits) is too large for buffer (%X)\n",
  537. obj_desc->common_field.bit_length, buffer_length));
  538. return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
  539. }
  540. ACPI_MEMSET (buffer, 0, buffer_length);
  541. /* Compute the number of datums (access width data items) */
  542. datum_count = ACPI_ROUND_UP_TO (
  543. obj_desc->common_field.bit_length,
  544. obj_desc->common_field.access_bit_width);
  545. field_datum_count = ACPI_ROUND_UP_TO (
  546. obj_desc->common_field.bit_length +
  547. obj_desc->common_field.start_field_bit_offset,
  548. obj_desc->common_field.access_bit_width);
  549. /* Priming read from the field */
  550. status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
  551. if (ACPI_FAILURE (status)) {
  552. return_ACPI_STATUS (status);
  553. }
  554. merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
  555. /* Read the rest of the field */
  556. for (i = 1; i < field_datum_count; i++) {
  557. /* Get next input datum from the field */
  558. field_offset += obj_desc->common_field.access_byte_width;
  559. status = acpi_ex_field_datum_io (obj_desc, field_offset,
  560. &raw_datum, ACPI_READ);
  561. if (ACPI_FAILURE (status)) {
  562. return_ACPI_STATUS (status);
  563. }
  564. /* Merge with previous datum if necessary */
  565. merged_datum |= raw_datum <<
  566. (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
  567. if (i == datum_count) {
  568. break;
  569. }
  570. /* Write merged datum to target buffer */
  571. ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
  572. ACPI_MIN(obj_desc->common_field.access_byte_width,
  573. buffer_length - buffer_offset));
  574. buffer_offset += obj_desc->common_field.access_byte_width;
  575. merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
  576. }
  577. /* Mask off any extra bits in the last datum */
  578. buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width;
  579. if (buffer_tail_bits) {
  580. merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
  581. }
  582. /* Write the last datum to the buffer */
  583. ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
  584. ACPI_MIN(obj_desc->common_field.access_byte_width,
  585. buffer_length - buffer_offset));
  586. return_ACPI_STATUS (AE_OK);
  587. }
  588. /*******************************************************************************
  589. *
  590. * FUNCTION: acpi_ex_insert_into_field
  591. *
  592. * PARAMETERS: obj_desc - Field to be written
  593. * Buffer - Data to be written
  594. * buffer_length - Length of Buffer
  595. *
  596. * RETURN: Status
  597. *
  598. * DESCRIPTION: Store the Buffer contents into the given field
  599. *
  600. ******************************************************************************/
  601. acpi_status
  602. acpi_ex_insert_into_field (
  603. union acpi_operand_object *obj_desc,
  604. void *buffer,
  605. u32 buffer_length)
  606. {
  607. acpi_status status;
  608. acpi_integer mask;
  609. acpi_integer merged_datum;
  610. acpi_integer raw_datum = 0;
  611. u32 field_offset = 0;
  612. u32 buffer_offset = 0;
  613. u32 buffer_tail_bits;
  614. u32 datum_count;
  615. u32 field_datum_count;
  616. u32 i;
  617. ACPI_FUNCTION_TRACE ("ex_insert_into_field");
  618. /* Validate input buffer */
  619. if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
  620. obj_desc->common_field.bit_length)) {
  621. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  622. "Field size %X (bits) is too large for buffer (%X)\n",
  623. obj_desc->common_field.bit_length, buffer_length));
  624. return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
  625. }
  626. /* Compute the number of datums (access width data items) */
  627. mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
  628. datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
  629. obj_desc->common_field.access_bit_width);
  630. field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
  631. obj_desc->common_field.start_field_bit_offset,
  632. obj_desc->common_field.access_bit_width);
  633. /* Get initial Datum from the input buffer */
  634. ACPI_MEMCPY (&raw_datum, buffer,
  635. ACPI_MIN(obj_desc->common_field.access_byte_width,
  636. buffer_length - buffer_offset));
  637. merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
  638. /* Write the entire field */
  639. for (i = 1; i < field_datum_count; i++) {
  640. /* Write merged datum to the target field */
  641. merged_datum &= mask;
  642. status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
  643. if (ACPI_FAILURE (status)) {
  644. return_ACPI_STATUS (status);
  645. }
  646. /* Start new output datum by merging with previous input datum */
  647. field_offset += obj_desc->common_field.access_byte_width;
  648. merged_datum = raw_datum >>
  649. (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
  650. mask = ACPI_INTEGER_MAX;
  651. if (i == datum_count) {
  652. break;
  653. }
  654. /* Get the next input datum from the buffer */
  655. buffer_offset += obj_desc->common_field.access_byte_width;
  656. ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
  657. ACPI_MIN(obj_desc->common_field.access_byte_width,
  658. buffer_length - buffer_offset));
  659. merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
  660. }
  661. /* Mask off any extra bits in the last datum */
  662. buffer_tail_bits = (obj_desc->common_field.bit_length +
  663. obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width;
  664. if (buffer_tail_bits) {
  665. mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
  666. }
  667. /* Write the last datum to the field */
  668. merged_datum &= mask;
  669. status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
  670. return_ACPI_STATUS (status);
  671. }