Update ACPI build wrappers to use new ACPICA(20050309) code.
[dragonfly.git] / sys / contrib / dev / acpica-unix-20050211 / interpreter / executer / exfldio.c
1 /******************************************************************************
2  *
3  * Module Name: exfldio - Aml Field I/O
4  *              $Revision: 113 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117
118 #define __EXFLDIO_C__
119
120 #include "acpi.h"
121 #include "acinterp.h"
122 #include "amlcode.h"
123 #include "acevents.h"
124 #include "acdispat.h"
125
126
127 #define _COMPONENT          ACPI_EXECUTER
128         ACPI_MODULE_NAME    ("exfldio")
129
130
131 /*******************************************************************************
132  *
133  * FUNCTION:    AcpiExSetupRegion
134  *
135  * PARAMETERS:  *ObjDesc                - Field to be read or written
136  *              FieldDatumByteOffset    - Byte offset of this datum within the
137  *                                        parent field
138  *
139  * RETURN:      Status
140  *
141  * DESCRIPTION: Common processing for AcpiExExtractFromField and
142  *              AcpiExInsertIntoField.  Initialize the Region if necessary and
143  *              validate the request.
144  *
145  ******************************************************************************/
146
147 ACPI_STATUS
148 AcpiExSetupRegion (
149     ACPI_OPERAND_OBJECT     *ObjDesc,
150     UINT32                  FieldDatumByteOffset)
151 {
152     ACPI_STATUS             Status = AE_OK;
153     ACPI_OPERAND_OBJECT     *RgnDesc;
154
155
156     ACPI_FUNCTION_TRACE_U32 ("ExSetupRegion", FieldDatumByteOffset);
157
158
159     RgnDesc = ObjDesc->CommonField.RegionObj;
160
161     /* We must have a valid region */
162
163     if (ACPI_GET_OBJECT_TYPE (RgnDesc) != ACPI_TYPE_REGION)
164     {
165         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
166             ACPI_GET_OBJECT_TYPE (RgnDesc),
167             AcpiUtGetObjectTypeName (RgnDesc)));
168
169         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
170     }
171
172     /*
173      * If the Region Address and Length have not been previously evaluated,
174      * evaluate them now and save the results.
175      */
176     if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
177     {
178         Status = AcpiDsGetRegionArguments (RgnDesc);
179         if (ACPI_FAILURE (Status))
180         {
181             return_ACPI_STATUS (Status);
182         }
183     }
184
185     if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)
186     {
187         /* SMBus has a non-linear address space */
188
189         return_ACPI_STATUS (AE_OK);
190     }
191
192 #ifdef ACPI_UNDER_DEVELOPMENT
193     /*
194      * If the Field access is AnyAcc, we can now compute the optimal
195      * access (because we know know the length of the parent region)
196      */
197     if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
198     {
199         if (ACPI_FAILURE (Status))
200         {
201             return_ACPI_STATUS (Status);
202         }
203     }
204 #endif
205
206     /*
207      * Validate the request.  The entire request from the byte offset for a
208      * length of one field datum (access width) must fit within the region.
209      * (Region length is specified in bytes)
210      */
211     if (RgnDesc->Region.Length < (ObjDesc->CommonField.BaseByteOffset
212                                     + FieldDatumByteOffset
213                                     + ObjDesc->CommonField.AccessByteWidth))
214     {
215         if (AcpiGbl_EnableInterpreterSlack)
216         {
217             /*
218              * Slack mode only:  We will go ahead and allow access to this
219              * field if it is within the region length rounded up to the next
220              * access width boundary.
221              */
222             if (ACPI_ROUND_UP (RgnDesc->Region.Length,
223                                 ObjDesc->CommonField.AccessByteWidth) >=
224                 (ObjDesc->CommonField.BaseByteOffset +
225                  (ACPI_NATIVE_UINT) ObjDesc->CommonField.AccessByteWidth +
226                  FieldDatumByteOffset))
227             {
228                 return_ACPI_STATUS (AE_OK);
229             }
230         }
231
232         if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
233         {
234             /*
235              * This is the case where the AccessType (AccWord, etc.) is wider
236              * than the region itself.  For example, a region of length one
237              * byte, and a field with Dword access specified.
238              */
239             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
240                 "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
241                 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
242                 ObjDesc->CommonField.AccessByteWidth,
243                 AcpiUtGetNodeName (RgnDesc->Region.Node), RgnDesc->Region.Length));
244         }
245
246         /*
247          * Offset rounded up to next multiple of field width
248          * exceeds region length, indicate an error
249          */
250         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
251             "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
252             AcpiUtGetNodeName (ObjDesc->CommonField.Node),
253             ObjDesc->CommonField.BaseByteOffset,
254             FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
255             AcpiUtGetNodeName (RgnDesc->Region.Node), RgnDesc->Region.Length));
256
257         return_ACPI_STATUS (AE_AML_REGION_LIMIT);
258     }
259
260     return_ACPI_STATUS (AE_OK);
261 }
262
263
264 /*******************************************************************************
265  *
266  * FUNCTION:    AcpiExAccessRegion
267  *
268  * PARAMETERS:  *ObjDesc                - Field to be read
269  *              FieldDatumByteOffset    - Byte offset of this datum within the
270  *                                        parent field
271  *              *Value                  - Where to store value (must at least
272  *                                        the size of ACPI_INTEGER)
273  *              Function                - Read or Write flag plus other region-
274  *                                        dependent flags
275  *
276  * RETURN:      Status
277  *
278  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
279  *
280  ******************************************************************************/
281
282 ACPI_STATUS
283 AcpiExAccessRegion (
284     ACPI_OPERAND_OBJECT     *ObjDesc,
285     UINT32                  FieldDatumByteOffset,
286     ACPI_INTEGER            *Value,
287     UINT32                  Function)
288 {
289     ACPI_STATUS             Status;
290     ACPI_OPERAND_OBJECT     *RgnDesc;
291     ACPI_PHYSICAL_ADDRESS   Address;
292
293
294     ACPI_FUNCTION_TRACE ("ExAccessRegion");
295
296
297     /*
298      * Ensure that the region operands are fully evaluated and verify
299      * the validity of the request
300      */
301     Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
302     if (ACPI_FAILURE (Status))
303     {
304         return_ACPI_STATUS (Status);
305     }
306
307     /*
308      * The physical address of this field datum is:
309      *
310      * 1) The base of the region, plus
311      * 2) The base offset of the field, plus
312      * 3) The current offset into the field
313      */
314     RgnDesc = ObjDesc->CommonField.RegionObj;
315     Address = RgnDesc->Region.Address
316                 + ObjDesc->CommonField.BaseByteOffset
317                 + FieldDatumByteOffset;
318
319     if ((Function & ACPI_IO_MASK) == ACPI_READ)
320     {
321         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
322     }
323     else
324     {
325         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
326     }
327
328     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
329         " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
330         AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
331         RgnDesc->Region.SpaceId,
332         ObjDesc->CommonField.AccessByteWidth,
333         ObjDesc->CommonField.BaseByteOffset,
334         FieldDatumByteOffset,
335         ACPI_FORMAT_UINT64 (Address)));
336
337     /* Invoke the appropriate AddressSpace/OpRegion handler */
338
339     Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function,
340                     Address, ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
341
342     if (ACPI_FAILURE (Status))
343     {
344         if (Status == AE_NOT_IMPLEMENTED)
345         {
346             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
347                 "Region %s(%X) not implemented\n",
348                 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
349                 RgnDesc->Region.SpaceId));
350         }
351         else if (Status == AE_NOT_EXIST)
352         {
353             ACPI_REPORT_ERROR ((
354                 "Region %s(%X) has no handler\n",
355                 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
356                 RgnDesc->Region.SpaceId));
357         }
358     }
359
360     return_ACPI_STATUS (Status);
361 }
362
363
364 /*******************************************************************************
365  *
366  * FUNCTION:    AcpiExRegisterOverflow
367  *
368  * PARAMETERS:  *ObjDesc                - Register(Field) to be written
369  *              Value                   - Value to be stored
370  *
371  * RETURN:      TRUE if value overflows the field, FALSE otherwise
372  *
373  * DESCRIPTION: Check if a value is out of range of the field being written.
374  *              Used to check if the values written to Index and Bank registers
375  *              are out of range.  Normally, the value is simply truncated
376  *              to fit the field, but this case is most likely a serious
377  *              coding error in the ASL.
378  *
379  ******************************************************************************/
380
381 BOOLEAN
382 AcpiExRegisterOverflow (
383     ACPI_OPERAND_OBJECT     *ObjDesc,
384     ACPI_INTEGER            Value)
385 {
386
387     if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
388     {
389         /*
390          * The field is large enough to hold the maximum integer, so we can
391          * never overflow it.
392          */
393         return (FALSE);
394     }
395
396     if (Value >= ((ACPI_INTEGER) 1 << ObjDesc->CommonField.BitLength))
397     {
398         /*
399          * The Value is larger than the maximum value that can fit into
400          * the register.
401          */
402         return (TRUE);
403     }
404
405     /* The Value will fit into the field with no truncation */
406
407     return (FALSE);
408 }
409
410
411 /*******************************************************************************
412  *
413  * FUNCTION:    AcpiExFieldDatumIo
414  *
415  * PARAMETERS:  *ObjDesc                - Field to be read
416  *              FieldDatumByteOffset    - Byte offset of this datum within the
417  *                                        parent field
418  *              *Value                  - Where to store value (must be 64 bits)
419  *              ReadWrite               - Read or Write flag
420  *
421  * RETURN:      Status
422  *
423  * DESCRIPTION: Read or Write a single datum of a field.  The FieldType is
424  *              demultiplexed here to handle the different types of fields
425  *              (BufferField, RegionField, IndexField, BankField)
426  *
427  ******************************************************************************/
428
429 ACPI_STATUS
430 AcpiExFieldDatumIo (
431     ACPI_OPERAND_OBJECT     *ObjDesc,
432     UINT32                  FieldDatumByteOffset,
433     ACPI_INTEGER            *Value,
434     UINT32                  ReadWrite)
435 {
436     ACPI_STATUS             Status;
437     ACPI_INTEGER            LocalValue;
438
439
440     ACPI_FUNCTION_TRACE_U32 ("ExFieldDatumIo", FieldDatumByteOffset);
441
442
443     if (ReadWrite == ACPI_READ)
444     {
445         if (!Value)
446         {
447             LocalValue = 0;
448             Value = &LocalValue;  /* To support reads without saving return value */
449         }
450
451         /* Clear the entire return buffer first, [Very Important!] */
452
453         *Value = 0;
454     }
455
456     /*
457      * The four types of fields are:
458      *
459      * BufferField - Read/write from/to a Buffer
460      * RegionField - Read/write from/to a Operation Region.
461      * BankField   - Write to a Bank Register, then read/write from/to an OpRegion
462      * IndexField  - Write to an Index Register, then read/write from/to a Data Register
463      */
464     switch (ACPI_GET_OBJECT_TYPE (ObjDesc))
465     {
466     case ACPI_TYPE_BUFFER_FIELD:
467         /*
468          * If the BufferField arguments have not been previously evaluated,
469          * evaluate them now and save the results.
470          */
471         if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
472         {
473             Status = AcpiDsGetBufferFieldArguments (ObjDesc);
474             if (ACPI_FAILURE (Status))
475             {
476                 return_ACPI_STATUS (Status);
477             }
478         }
479
480         if (ReadWrite == ACPI_READ)
481         {
482             /*
483              * Copy the data from the source buffer.
484              * Length is the field width in bytes.
485              */
486             ACPI_MEMCPY (Value, (ObjDesc->BufferField.BufferObj)->Buffer.Pointer
487                             + ObjDesc->BufferField.BaseByteOffset
488                             + FieldDatumByteOffset,
489                             ObjDesc->CommonField.AccessByteWidth);
490         }
491         else
492         {
493             /*
494              * Copy the data to the target buffer.
495              * Length is the field width in bytes.
496              */
497             ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer
498                     + ObjDesc->BufferField.BaseByteOffset
499                     + FieldDatumByteOffset,
500                     Value, ObjDesc->CommonField.AccessByteWidth);
501         }
502
503         Status = AE_OK;
504         break;
505
506
507     case ACPI_TYPE_LOCAL_BANK_FIELD:
508
509         /* Ensure that the BankValue is not beyond the capacity of the register */
510
511         if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
512                                     (ACPI_INTEGER) ObjDesc->BankField.Value))
513         {
514             return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
515         }
516
517         /*
518          * For BankFields, we must write the BankValue to the BankRegister
519          * (itself a RegionField) before we can access the data.
520          */
521         Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
522                                 &ObjDesc->BankField.Value,
523                                 sizeof (ObjDesc->BankField.Value));
524         if (ACPI_FAILURE (Status))
525         {
526             return_ACPI_STATUS (Status);
527         }
528
529         /*
530          * Now that the Bank has been selected, fall through to the
531          * RegionField case and write the datum to the Operation Region
532          */
533
534         /*lint -fallthrough */
535
536
537     case ACPI_TYPE_LOCAL_REGION_FIELD:
538         /*
539          * For simple RegionFields, we just directly access the owning
540          * Operation Region.
541          */
542         Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
543                         ReadWrite);
544         break;
545
546
547     case ACPI_TYPE_LOCAL_INDEX_FIELD:
548
549
550         /* Ensure that the IndexValue is not beyond the capacity of the register */
551
552         if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
553                                     (ACPI_INTEGER) ObjDesc->IndexField.Value))
554         {
555             return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
556         }
557
558         /* Write the index value to the IndexRegister (itself a RegionField) */
559
560         FieldDatumByteOffset += ObjDesc->IndexField.Value;
561
562         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
563                 "Write to Index Register: Value %8.8X\n",
564                 FieldDatumByteOffset));
565
566         Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
567                                 &FieldDatumByteOffset,
568                                 sizeof (FieldDatumByteOffset));
569         if (ACPI_FAILURE (Status))
570         {
571             return_ACPI_STATUS (Status);
572         }
573
574         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
575                 "I/O to Data Register: ValuePtr %p\n",
576                 Value));
577
578         if (ReadWrite == ACPI_READ)
579         {
580             /* Read the datum from the DataRegister */
581
582             Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
583                             Value, sizeof (ACPI_INTEGER));
584         }
585         else
586         {
587             /* Write the datum to the DataRegister */
588
589             Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
590                             Value, sizeof (ACPI_INTEGER));
591         }
592         break;
593
594
595     default:
596
597         ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
598             ACPI_GET_OBJECT_TYPE (ObjDesc)));
599         Status = AE_AML_INTERNAL;
600         break;
601     }
602
603     if (ACPI_SUCCESS (Status))
604     {
605         if (ReadWrite == ACPI_READ)
606         {
607             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n",
608                                 ACPI_FORMAT_UINT64 (*Value),
609                                 ObjDesc->CommonField.AccessByteWidth));
610         }
611         else
612         {
613             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n",
614                                 ACPI_FORMAT_UINT64 (*Value),
615                                 ObjDesc->CommonField.AccessByteWidth));
616         }
617     }
618
619     return_ACPI_STATUS (Status);
620 }
621
622
623 /*******************************************************************************
624  *
625  * FUNCTION:    AcpiExWriteWithUpdateRule
626  *
627  * PARAMETERS:  *ObjDesc            - Field to be set
628  *              Value               - Value to store
629  *
630  * RETURN:      Status
631  *
632  * DESCRIPTION: Apply the field update rule to a field write
633  *
634  ******************************************************************************/
635
636 ACPI_STATUS
637 AcpiExWriteWithUpdateRule (
638     ACPI_OPERAND_OBJECT     *ObjDesc,
639     ACPI_INTEGER            Mask,
640     ACPI_INTEGER            FieldValue,
641     UINT32                  FieldDatumByteOffset)
642 {
643     ACPI_STATUS             Status = AE_OK;
644     ACPI_INTEGER            MergedValue;
645     ACPI_INTEGER            CurrentValue;
646
647
648     ACPI_FUNCTION_TRACE_U32 ("ExWriteWithUpdateRule", Mask);
649
650
651     /* Start with the new bits  */
652
653     MergedValue = FieldValue;
654
655     /* If the mask is all ones, we don't need to worry about the update rule */
656
657     if (Mask != ACPI_INTEGER_MAX)
658     {
659         /* Decode the update rule */
660
661         switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
662         {
663         case AML_FIELD_UPDATE_PRESERVE:
664             /*
665              * Check if update rule needs to be applied (not if mask is all
666              * ones)  The left shift drops the bits we want to ignore.
667              */
668             if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
669                            ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
670             {
671                 /*
672                  * Read the current contents of the byte/word/dword containing
673                  * the field, and merge with the new field value.
674                  */
675                 Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
676                                 &CurrentValue, ACPI_READ);
677                 if (ACPI_FAILURE (Status))
678                 {
679                     return_ACPI_STATUS (Status);
680                 }
681
682                 MergedValue |= (CurrentValue & ~Mask);
683             }
684             break;
685
686         case AML_FIELD_UPDATE_WRITE_AS_ONES:
687
688             /* Set positions outside the field to all ones */
689
690             MergedValue |= ~Mask;
691             break;
692
693         case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
694
695             /* Set positions outside the field to all zeros */
696
697             MergedValue &= Mask;
698             break;
699
700         default:
701
702             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
703                 "WriteWithUpdateRule: Unknown UpdateRule setting: %X\n",
704                 (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
705             return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
706         }
707     }
708
709     ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
710         "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
711         ACPI_FORMAT_UINT64 (Mask),
712         FieldDatumByteOffset,
713         ObjDesc->CommonField.AccessByteWidth,
714         ACPI_FORMAT_UINT64 (FieldValue),
715         ACPI_FORMAT_UINT64 (MergedValue)));
716
717     /* Write the merged value */
718
719     Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
720                     &MergedValue, ACPI_WRITE);
721
722     return_ACPI_STATUS (Status);
723 }
724
725
726 /*******************************************************************************
727  *
728  * FUNCTION:    AcpiExExtractFromField
729  *
730  * PARAMETERS:  ObjDesc             - Field to be read
731  *              Buffer              - Where to store the field data
732  *              BufferLength        - Length of Buffer
733  *
734  * RETURN:      Status
735  *
736  * DESCRIPTION: Retrieve the current value of the given field
737  *
738  ******************************************************************************/
739
740 ACPI_STATUS
741 AcpiExExtractFromField (
742     ACPI_OPERAND_OBJECT     *ObjDesc,
743     void                    *Buffer,
744     UINT32                  BufferLength)
745 {
746     ACPI_STATUS             Status;
747     ACPI_INTEGER            RawDatum;
748     ACPI_INTEGER            MergedDatum;
749     UINT32                  FieldOffset = 0;
750     UINT32                  BufferOffset = 0;
751     UINT32                  BufferTailBits;
752     UINT32                  DatumCount;
753     UINT32                  FieldDatumCount;
754     UINT32                  i;
755
756
757     ACPI_FUNCTION_TRACE ("ExExtractFromField");
758
759
760     /* Validate target buffer and clear it */
761
762     if (BufferLength < ACPI_ROUND_BITS_UP_TO_BYTES (
763                             ObjDesc->CommonField.BitLength))
764     {
765         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
766             "Field size %X (bits) is too large for buffer (%X)\n",
767             ObjDesc->CommonField.BitLength, BufferLength));
768
769         return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
770     }
771     ACPI_MEMSET (Buffer, 0, BufferLength);
772
773     /* Compute the number of datums (access width data items) */
774
775     DatumCount = ACPI_ROUND_UP_TO (
776                         ObjDesc->CommonField.BitLength,
777                         ObjDesc->CommonField.AccessBitWidth);
778     FieldDatumCount = ACPI_ROUND_UP_TO (
779                         ObjDesc->CommonField.BitLength +
780                         ObjDesc->CommonField.StartFieldBitOffset,
781                         ObjDesc->CommonField.AccessBitWidth);
782
783     /* Priming read from the field */
784
785     Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
786     if (ACPI_FAILURE (Status))
787     {
788         return_ACPI_STATUS (Status);
789     }
790     MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
791
792     /* Read the rest of the field */
793
794     for (i = 1; i < FieldDatumCount; i++)
795     {
796         /* Get next input datum from the field */
797
798         FieldOffset += ObjDesc->CommonField.AccessByteWidth;
799         Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
800                         &RawDatum, ACPI_READ);
801         if (ACPI_FAILURE (Status))
802         {
803             return_ACPI_STATUS (Status);
804         }
805
806         /* Merge with previous datum if necessary */
807
808         MergedDatum |= RawDatum <<
809             (ObjDesc->CommonField.AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
810
811         if (i == DatumCount)
812         {
813             break;
814         }
815
816         /* Write merged datum to target buffer */
817
818         ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
819             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
820                      BufferLength - BufferOffset));
821
822         BufferOffset += ObjDesc->CommonField.AccessByteWidth;
823         MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
824     }
825
826     /* Mask off any extra bits in the last datum */
827
828     BufferTailBits = ObjDesc->CommonField.BitLength % ObjDesc->CommonField.AccessBitWidth;
829     if (BufferTailBits)
830     {
831         MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
832     }
833
834     /* Write the last datum to the buffer */
835
836     ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
837         ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
838                  BufferLength - BufferOffset));
839
840     return_ACPI_STATUS (AE_OK);
841 }
842
843
844 /*******************************************************************************
845  *
846  * FUNCTION:    AcpiExInsertIntoField
847  *
848  * PARAMETERS:  ObjDesc             - Field to be written
849  *              Buffer              - Data to be written
850  *              BufferLength        - Length of Buffer
851  *
852  * RETURN:      Status
853  *
854  * DESCRIPTION: Store the Buffer contents into the given field
855  *
856  ******************************************************************************/
857
858 ACPI_STATUS
859 AcpiExInsertIntoField (
860     ACPI_OPERAND_OBJECT     *ObjDesc,
861     void                    *Buffer,
862     UINT32                  BufferLength)
863 {
864     ACPI_STATUS             Status;
865     ACPI_INTEGER            Mask;
866     ACPI_INTEGER            MergedDatum;
867     ACPI_INTEGER            RawDatum = 0;
868     UINT32                  FieldOffset = 0;
869     UINT32                  BufferOffset = 0;
870     UINT32                  BufferTailBits;
871     UINT32                  DatumCount;
872     UINT32                  FieldDatumCount;
873     UINT32                  i;
874
875
876     ACPI_FUNCTION_TRACE ("ExInsertIntoField");
877
878
879     /* Validate input buffer */
880
881     if (BufferLength < ACPI_ROUND_BITS_UP_TO_BYTES (
882                             ObjDesc->CommonField.BitLength))
883     {
884         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
885             "Field size %X (bits) is too large for buffer (%X)\n",
886             ObjDesc->CommonField.BitLength, BufferLength));
887
888         return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
889     }
890
891     /* Compute the number of datums (access width data items) */
892
893     Mask = ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
894     DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
895                     ObjDesc->CommonField.AccessBitWidth);
896     FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
897                         ObjDesc->CommonField.StartFieldBitOffset,
898                         ObjDesc->CommonField.AccessBitWidth);
899
900     /* Get initial Datum from the input buffer */
901
902     ACPI_MEMCPY (&RawDatum, Buffer,
903         ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
904                  BufferLength - BufferOffset));
905
906     MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
907
908     /* Write the entire field */
909
910     for (i = 1; i < FieldDatumCount; i++)
911     {
912         /* Write merged datum to the target field */
913
914         MergedDatum &= Mask;
915         Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, MergedDatum, FieldOffset);
916         if (ACPI_FAILURE (Status))
917         {
918             return_ACPI_STATUS (Status);
919         }
920
921         /* Start new output datum by merging with previous input datum */
922
923         FieldOffset += ObjDesc->CommonField.AccessByteWidth;
924         MergedDatum = RawDatum >>
925             (ObjDesc->CommonField.AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
926         Mask = ACPI_INTEGER_MAX;
927
928         if (i == DatumCount)
929         {
930             break;
931         }
932
933         /* Get the next input datum from the buffer */
934
935         BufferOffset += ObjDesc->CommonField.AccessByteWidth;
936         ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset,
937             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
938                      BufferLength - BufferOffset));
939         MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
940     }
941
942     /* Mask off any extra bits in the last datum */
943
944     BufferTailBits = (ObjDesc->CommonField.BitLength +
945             ObjDesc->CommonField.StartFieldBitOffset) % ObjDesc->CommonField.AccessBitWidth;
946     if (BufferTailBits)
947     {
948         Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
949     }
950
951     /* Write the last datum to the field */
952
953     MergedDatum &= Mask;
954     Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, MergedDatum, FieldOffset);
955
956     return_ACPI_STATUS (Status);
957 }
958
959