Sync ACPICA with Intel's version 20150204.
[dragonfly.git] / sys / contrib / dev / acpica / source / tools / acpiexec / aeregion.c
1 /******************************************************************************
2  *
3  * Module Name: aeregion - Operation region support for acpiexec
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include "aecommon.h"
45
46 #define _COMPONENT          ACPI_TOOLS
47         ACPI_MODULE_NAME    ("aeregion")
48
49
50 /* Local prototypes */
51
52 static ACPI_STATUS
53 AeRegionInit (
54     ACPI_HANDLE             RegionHandle,
55     UINT32                  Function,
56     void                    *HandlerContext,
57     void                    **RegionContext);
58
59 static ACPI_STATUS
60 AeInstallEcHandler (
61     ACPI_HANDLE             ObjHandle,
62     UINT32                  Level,
63     void                    *Context,
64     void                    **ReturnValue);
65
66 static ACPI_STATUS
67 AeInstallPciHandler (
68     ACPI_HANDLE             ObjHandle,
69     UINT32                  Level,
70     void                    *Context,
71     void                    **ReturnValue);
72
73
74 static AE_DEBUG_REGIONS     AeRegions;
75 BOOLEAN                     AcpiGbl_DisplayRegionAccess = FALSE;
76 ACPI_CONNECTION_INFO        AeMyContext;
77
78
79 /*
80  * We will override some of the default region handlers, especially
81  * the SystemMemory handler, which must be implemented locally.
82  * These handlers are installed "early" - before any _REG methods
83  * are executed - since they are special in the sense that the ACPI spec
84  * declares that they must "always be available". Cannot override the
85  * DataTable region handler either -- needed for test execution.
86  *
87  * NOTE: The local region handler will simulate access to these address
88  * spaces by creating a memory buffer behind each operation region.
89  */
90 static ACPI_ADR_SPACE_TYPE  DefaultSpaceIdList[] =
91 {
92     ACPI_ADR_SPACE_SYSTEM_MEMORY,
93     ACPI_ADR_SPACE_SYSTEM_IO,
94     ACPI_ADR_SPACE_PCI_CONFIG,
95     ACPI_ADR_SPACE_EC
96 };
97
98 /*
99  * We will install handlers for some of the various address space IDs.
100  * Test one user-defined address space (used by aslts).
101  */
102 #define ACPI_ADR_SPACE_USER_DEFINED1        0x80
103 #define ACPI_ADR_SPACE_USER_DEFINED2        0xE4
104
105 static ACPI_ADR_SPACE_TYPE  SpaceIdList[] =
106 {
107     ACPI_ADR_SPACE_SMBUS,
108     ACPI_ADR_SPACE_CMOS,
109     ACPI_ADR_SPACE_PCI_BAR_TARGET,
110     ACPI_ADR_SPACE_IPMI,
111     ACPI_ADR_SPACE_GPIO,
112     ACPI_ADR_SPACE_GSBUS,
113     ACPI_ADR_SPACE_FIXED_HARDWARE,
114     ACPI_ADR_SPACE_USER_DEFINED1,
115     ACPI_ADR_SPACE_USER_DEFINED2
116 };
117
118
119 /******************************************************************************
120  *
121  * FUNCTION:    AeRegionInit
122  *
123  * PARAMETERS:  Region init handler
124  *
125  * RETURN:      Status
126  *
127  * DESCRIPTION: Opregion init function.
128  *
129  *****************************************************************************/
130
131 static ACPI_STATUS
132 AeRegionInit (
133     ACPI_HANDLE                 RegionHandle,
134     UINT32                      Function,
135     void                        *HandlerContext,
136     void                        **RegionContext)
137 {
138
139     if (Function == ACPI_REGION_DEACTIVATE)
140     {
141         *RegionContext = NULL;
142     }
143     else
144     {
145         *RegionContext = RegionHandle;
146     }
147
148     return (AE_OK);
149 }
150
151
152 void
153 AeInstallRegionHandlers (
154     void)
155 {
156     UINT32                  i;
157     ACPI_STATUS             Status;
158
159     /*
160      * Install handlers for some of the "device driver" address spaces
161      * such as SMBus, etc.
162      */
163     for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++)
164     {
165         /* Install handler at the root object */
166
167         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
168                     SpaceIdList[i], AeRegionHandler,
169                     AeRegionInit, &AeMyContext);
170         if (ACPI_FAILURE (Status))
171         {
172             ACPI_EXCEPTION ((AE_INFO, Status,
173                 "Could not install an OpRegion handler for %s space(%u)",
174                 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i]));
175             return;
176         }
177     }
178 }
179
180
181 void
182 AeOverrideRegionHandlers (
183     void)
184 {
185     UINT32                  i;
186     ACPI_STATUS             Status;
187
188     /*
189      * Install handlers that will override the default handlers for some of
190      * the space IDs.
191      */
192     for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++)
193     {
194         /* Install handler at the root object */
195
196         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
197                     DefaultSpaceIdList[i], AeRegionHandler,
198                     AeRegionInit, &AeMyContext);
199         if (ACPI_FAILURE (Status))
200         {
201             ACPI_EXCEPTION ((AE_INFO, Status,
202                 "Could not install a default OpRegion handler for %s space(%u)",
203                 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]),
204                 DefaultSpaceIdList[i]));
205             return;
206         }
207     }
208 }
209
210
211 /*******************************************************************************
212  *
213  * FUNCTION:    AeInstallDeviceHandlers,
214  *              AeInstallEcHandler,
215  *              AeInstallPciHandler
216  *
217  * PARAMETERS:  ACPI_WALK_NAMESPACE callback
218  *
219  * RETURN:      Status
220  *
221  * DESCRIPTION: Walk entire namespace, install a handler for every EC
222  *              and PCI device found.
223  *
224  ******************************************************************************/
225
226 static ACPI_STATUS
227 AeInstallEcHandler (
228     ACPI_HANDLE             ObjHandle,
229     UINT32                  Level,
230     void                    *Context,
231     void                    **ReturnValue)
232 {
233     ACPI_STATUS             Status;
234
235
236     /* Install the handler for this EC device */
237
238     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_EC,
239         AeRegionHandler, AeRegionInit, &AeMyContext);
240     if (ACPI_FAILURE (Status))
241     {
242         ACPI_EXCEPTION ((AE_INFO, Status,
243             "Could not install an OpRegion handler for EC device (%p)",
244             ObjHandle));
245     }
246
247     return (Status);
248 }
249
250
251 static ACPI_STATUS
252 AeInstallPciHandler (
253     ACPI_HANDLE             ObjHandle,
254     UINT32                  Level,
255     void                    *Context,
256     void                    **ReturnValue)
257 {
258     ACPI_STATUS             Status;
259
260
261     /* Install memory and I/O handlers for the PCI device */
262
263     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_IO,
264         AeRegionHandler, AeRegionInit, &AeMyContext);
265     if (ACPI_FAILURE (Status))
266     {
267         ACPI_EXCEPTION ((AE_INFO, Status,
268             "Could not install an OpRegion handler for PCI device (%p)",
269             ObjHandle));
270     }
271
272     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_MEMORY,
273         AeRegionHandler, AeRegionInit, &AeMyContext);
274     if (ACPI_FAILURE (Status))
275     {
276         ACPI_EXCEPTION ((AE_INFO, Status,
277             "Could not install an OpRegion handler for PCI device (%p)",
278             ObjHandle));
279     }
280
281     return (AE_CTRL_TERMINATE);
282 }
283
284
285 ACPI_STATUS
286 AeInstallDeviceHandlers (
287     void)
288 {
289
290     /* Find all Embedded Controller devices */
291
292     AcpiGetDevices ("PNP0C09", AeInstallEcHandler, NULL, NULL);
293
294     /* Install a PCI handler */
295
296     AcpiGetDevices ("PNP0A08", AeInstallPciHandler, NULL, NULL);
297     return (AE_OK);
298 }
299
300
301 /******************************************************************************
302  *
303  * FUNCTION:    AeRegionHandler
304  *
305  * PARAMETERS:  Standard region handler parameters
306  *
307  * RETURN:      Status
308  *
309  * DESCRIPTION: Test handler - Handles some dummy regions via memory that can
310  *              be manipulated in Ring 3. Simulates actual reads and writes.
311  *
312  *****************************************************************************/
313
314 ACPI_STATUS
315 AeRegionHandler (
316     UINT32                  Function,
317     ACPI_PHYSICAL_ADDRESS   Address,
318     UINT32                  BitWidth,
319     UINT64                  *Value,
320     void                    *HandlerContext,
321     void                    *RegionContext)
322 {
323
324     ACPI_OPERAND_OBJECT     *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
325     UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Value);
326     UINT8                   *OldBuffer;
327     UINT8                   *NewBuffer;
328     ACPI_PHYSICAL_ADDRESS   BaseAddress;
329     ACPI_PHYSICAL_ADDRESS   BaseAddressEnd;
330     ACPI_PHYSICAL_ADDRESS   RegionAddress;
331     ACPI_PHYSICAL_ADDRESS   RegionAddressEnd;
332     ACPI_SIZE               Length;
333     BOOLEAN                 BufferExists;
334     BOOLEAN                 BufferResize;
335     AE_REGION               *RegionElement;
336     void                    *BufferValue;
337     ACPI_STATUS             Status;
338     UINT32                  ByteWidth;
339     UINT32                  RegionLength;
340     UINT32                  i;
341     UINT8                   SpaceId;
342     ACPI_CONNECTION_INFO    *MyContext;
343     UINT32                  Value1;
344     UINT32                  Value2;
345     ACPI_RESOURCE           *Resource;
346
347
348     ACPI_FUNCTION_NAME (AeRegionHandler);
349
350     /*
351      * If the object is not a region, simply return
352      */
353     if (RegionObject->Region.Type != ACPI_TYPE_REGION)
354     {
355         return (AE_OK);
356     }
357
358     /* Check that we actually got back our context parameter */
359
360     if (HandlerContext != &AeMyContext)
361     {
362         printf ("Region handler received incorrect context %p, should be %p\n",
363             HandlerContext, &AeMyContext);
364     }
365
366     MyContext = ACPI_CAST_PTR (ACPI_CONNECTION_INFO, HandlerContext);
367
368     /*
369      * Find the region's address space and length before searching
370      * the linked list.
371      */
372     BaseAddress = RegionObject->Region.Address;
373     Length = (ACPI_SIZE) RegionObject->Region.Length;
374     SpaceId = RegionObject->Region.SpaceId;
375
376     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n",
377             AcpiUtGetRegionName (RegionObject->Region.SpaceId),
378             (UINT32) Address));
379
380     /*
381      * Region support can be disabled with the -do option.
382      * We use this to support dynamically loaded tables where we pass a valid
383      * address to the AML.
384      */
385     if (AcpiGbl_DbOpt_NoRegionSupport)
386     {
387         BufferValue = ACPI_TO_POINTER (Address);
388         ByteWidth = (BitWidth / 8);
389
390         if (BitWidth % 8)
391         {
392             ByteWidth += 1;
393         }
394         goto DoFunction;
395     }
396
397     switch (SpaceId)
398     {
399     case ACPI_ADR_SPACE_SYSTEM_IO:
400         /*
401          * For I/O space, exercise the port validation
402          * Note: ReadPort currently always returns all ones, length=BitLength
403          */
404         switch (Function & ACPI_IO_MASK)
405         {
406         case ACPI_READ:
407
408             if (BitWidth == 64)
409             {
410                 /* Split the 64-bit request into two 32-bit requests */
411
412                 Status = AcpiHwReadPort (Address, &Value1, 32);
413                 AE_CHECK_OK (AcpiHwReadPort, Status);
414                 Status = AcpiHwReadPort (Address+4, &Value2, 32);
415                 AE_CHECK_OK (AcpiHwReadPort, Status);
416
417                 *Value = Value1 | ((UINT64) Value2 << 32);
418             }
419             else
420             {
421                 Status = AcpiHwReadPort (Address, &Value1, BitWidth);
422                 AE_CHECK_OK (AcpiHwReadPort, Status);
423                 *Value = (UINT64) Value1;
424             }
425             break;
426
427         case ACPI_WRITE:
428
429             if (BitWidth == 64)
430             {
431                 /* Split the 64-bit request into two 32-bit requests */
432
433                 Status = AcpiHwWritePort (Address, ACPI_LODWORD (*Value), 32);
434                 AE_CHECK_OK (AcpiHwWritePort, Status);
435                 Status = AcpiHwWritePort (Address+4, ACPI_HIDWORD (*Value), 32);
436                 AE_CHECK_OK (AcpiHwWritePort, Status);
437             }
438             else
439             {
440                 Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth);
441                 AE_CHECK_OK (AcpiHwWritePort, Status);
442             }
443             break;
444
445         default:
446
447             Status = AE_BAD_PARAMETER;
448             break;
449         }
450
451         if (ACPI_FAILURE (Status))
452         {
453             return (Status);
454         }
455
456         /* Now go ahead and simulate the hardware */
457         break;
458
459     /*
460      * SMBus and GenericSerialBus support the various bidirectional
461      * protocols.
462      */
463     case ACPI_ADR_SPACE_SMBUS:
464     case ACPI_ADR_SPACE_GSBUS:  /* ACPI 5.0 */
465
466         Length = 0;
467
468         switch (Function & ACPI_IO_MASK)
469         {
470         case ACPI_READ:
471
472             switch (Function >> 16)
473             {
474             case AML_FIELD_ATTRIB_QUICK:
475
476                 Length = 0;
477                 break;
478
479             case AML_FIELD_ATTRIB_SEND_RCV:
480             case AML_FIELD_ATTRIB_BYTE:
481
482                 Length = 1;
483                 break;
484
485             case AML_FIELD_ATTRIB_WORD:
486             case AML_FIELD_ATTRIB_WORD_CALL:
487
488                 Length = 2;
489                 break;
490
491             case AML_FIELD_ATTRIB_BLOCK:
492             case AML_FIELD_ATTRIB_BLOCK_CALL:
493
494                 Length = 32;
495                 break;
496
497             case AML_FIELD_ATTRIB_MULTIBYTE:
498             case AML_FIELD_ATTRIB_RAW_BYTES:
499             case AML_FIELD_ATTRIB_RAW_PROCESS:
500
501                 Length = MyContext->AccessLength;
502                 break;
503
504             default:
505
506                 break;
507             }
508             break;
509
510         case ACPI_WRITE:
511
512             switch (Function >> 16)
513             {
514             case AML_FIELD_ATTRIB_QUICK:
515             case AML_FIELD_ATTRIB_SEND_RCV:
516             case AML_FIELD_ATTRIB_BYTE:
517             case AML_FIELD_ATTRIB_WORD:
518             case AML_FIELD_ATTRIB_BLOCK:
519
520                 Length = 0;
521                 break;
522
523             case AML_FIELD_ATTRIB_WORD_CALL:
524                 Length = 2;
525                 break;
526
527             case AML_FIELD_ATTRIB_BLOCK_CALL:
528                 Length = 32;
529                 break;
530
531             case AML_FIELD_ATTRIB_MULTIBYTE:
532             case AML_FIELD_ATTRIB_RAW_BYTES:
533             case AML_FIELD_ATTRIB_RAW_PROCESS:
534
535                 Length = MyContext->AccessLength;
536                 break;
537
538             default:
539
540                 break;
541             }
542             break;
543
544         default:
545
546             break;
547         }
548
549         if (AcpiGbl_DisplayRegionAccess)
550         {
551             AcpiOsPrintf ("AcpiExec: %s "
552                 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X",
553                 AcpiUtGetRegionName (SpaceId),
554                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
555                 (UINT32) (Function >> 16),
556                 (UINT32) Address, (UINT32) BaseAddress,
557                 Length, BitWidth, Buffer[1]);
558
559             /* GenericSerialBus has a Connection() parameter */
560
561             if (SpaceId == ACPI_ADR_SPACE_GSBUS)
562             {
563                 Status = AcpiBufferToResource (MyContext->Connection,
564                     MyContext->Length, &Resource);
565
566                 AcpiOsPrintf (" [AccLen %.2X Conn %p]",
567                     MyContext->AccessLength, MyContext->Connection);
568             }
569             AcpiOsPrintf ("\n");
570         }
571
572         /* Setup the return buffer. Note: ASLTS depends on these fill values */
573
574         for (i = 0; i < Length; i++)
575         {
576             Buffer[i+2] = (UINT8) (0xA0 + i);
577         }
578
579         Buffer[0] = 0x7A;
580         Buffer[1] = (UINT8) Length;
581         return (AE_OK);
582
583
584     case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
585
586         if (AcpiGbl_DisplayRegionAccess)
587         {
588             AcpiOsPrintf ("AcpiExec: IPMI "
589                 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n",
590                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
591                 (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress,
592                 Length, BitWidth, Buffer[1]);
593         }
594
595         /*
596          * Regardless of a READ or WRITE, this handler is passed a 66-byte
597          * buffer in which to return the IPMI status/length/data.
598          *
599          * Return some example data to show use of the bidirectional buffer
600          */
601         Buffer[0] = 0;       /* Status byte */
602         Buffer[1] = 64;      /* Return buffer data length */
603         Buffer[2] = 0;       /* Completion code */
604         Buffer[3] = 0;       /* Reserved */
605
606         /*
607          * Fill the 66-byte buffer with the return data.
608          * Note: ASLTS depends on these fill values.
609          */
610         for (i = 4; i < 66; i++)
611         {
612             Buffer[i] = (UINT8) (i);
613         }
614         return (AE_OK);
615
616     /*
617      * GPIO has some special semantics:
618      * 1) Address is the pin number index into the Connection() pin list
619      * 2) BitWidth is the actual number of bits (pins) defined by the field
620      */
621     case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */
622
623         if (AcpiGbl_DisplayRegionAccess)
624         {
625             AcpiOsPrintf ("AcpiExec: GPIO "
626                 "%s: Addr %.4X Width %X Conn %p\n",
627                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
628                 (UINT32) Address, BitWidth, MyContext->Connection);
629         }
630         return (AE_OK);
631
632     default:
633         break;
634     }
635
636     /*
637      * Search through the linked list for this region's buffer
638      */
639     BufferExists = FALSE;
640     BufferResize = FALSE;
641     RegionElement = AeRegions.RegionList;
642
643     if (AeRegions.NumberOfRegions)
644     {
645         BaseAddressEnd = BaseAddress + Length - 1;
646         while (!BufferExists && RegionElement)
647         {
648             RegionAddress = RegionElement->Address;
649             RegionAddressEnd = RegionElement->Address + RegionElement->Length - 1;
650             RegionLength = RegionElement->Length;
651
652             /*
653              * Overlapping Region Support
654              *
655              * While searching through the region buffer list, determine if an
656              * overlap exists between the requested buffer space and the current
657              * RegionElement space. If there is an overlap then replace the old
658              * buffer with a new buffer of increased size before continuing to
659              * do the read or write
660              */
661             if (RegionElement->SpaceId != SpaceId ||
662                 BaseAddressEnd < RegionAddress ||
663                 BaseAddress > RegionAddressEnd)
664             {
665                 /*
666                  * Requested buffer is outside of the current RegionElement
667                  * bounds
668                  */
669                 RegionElement = RegionElement->NextRegion;
670             }
671             else
672             {
673                 /*
674                  * Some amount of buffer space sharing exists. There are 4 cases
675                  * to consider:
676                  *
677                  * 1. Right overlap
678                  * 2. Left overlap
679                  * 3. Left and right overlap
680                  * 4. Fully contained - no resizing required
681                  */
682                 BufferExists = TRUE;
683
684                 if ((BaseAddress >= RegionAddress) &&
685                     (BaseAddress <= RegionAddressEnd) &&
686                     (BaseAddressEnd > RegionAddressEnd))
687                 {
688                     /* Right overlap */
689
690                     RegionElement->Length = BaseAddress -
691                         RegionAddress + Length;
692                     BufferResize = TRUE;
693                 }
694
695                 else if ((BaseAddressEnd >= RegionAddress) &&
696                          (BaseAddressEnd <= RegionAddressEnd) &&
697                          (BaseAddress < RegionAddress))
698                 {
699                     /* Left overlap */
700
701                     RegionElement->Address = BaseAddress;
702                     RegionElement->Length = RegionAddress -
703                         BaseAddress + RegionElement->Length;
704                     BufferResize = TRUE;
705                 }
706
707                 else if ((BaseAddress < RegionAddress) &&
708                          (BaseAddressEnd > RegionAddressEnd))
709                 {
710                     /* Left and right overlap */
711
712                     RegionElement->Address = BaseAddress;
713                     RegionElement->Length = Length;
714                     BufferResize = TRUE;
715                 }
716
717                 /*
718                  * only remaining case is fully contained for which we don't
719                  * need to do anything
720                  */
721                 if (BufferResize)
722                 {
723                     NewBuffer = AcpiOsAllocate (RegionElement->Length);
724                     if (!NewBuffer)
725                     {
726                         return (AE_NO_MEMORY);
727                     }
728
729                     OldBuffer = RegionElement->Buffer;
730                     RegionElement->Buffer = NewBuffer;
731                     NewBuffer = NULL;
732
733                     /* Initialize the region with the default fill value */
734
735                     ACPI_MEMSET (RegionElement->Buffer,
736                         AcpiGbl_RegionFillValue, RegionElement->Length);
737
738                     /*
739                      * Get BufferValue to point (within the new buffer) to the
740                      * base address of the old buffer
741                      */
742                     BufferValue = (UINT8 *) RegionElement->Buffer +
743                         (UINT64) RegionAddress -
744                         (UINT64) RegionElement->Address;
745
746                     /*
747                      * Copy the old buffer to its same location within the new
748                      * buffer
749                      */
750                     ACPI_MEMCPY (BufferValue, OldBuffer, RegionLength);
751                     AcpiOsFree (OldBuffer);
752                 }
753             }
754         }
755     }
756
757     /*
758      * If the Region buffer does not exist, create it now
759      */
760     if (!BufferExists)
761     {
762         /* Do the memory allocations first */
763
764         RegionElement = AcpiOsAllocate (sizeof (AE_REGION));
765         if (!RegionElement)
766         {
767             return (AE_NO_MEMORY);
768         }
769
770         RegionElement->Buffer = AcpiOsAllocate (Length);
771         if (!RegionElement->Buffer)
772         {
773             AcpiOsFree (RegionElement);
774             return (AE_NO_MEMORY);
775         }
776
777         /* Initialize the region with the default fill value */
778
779         ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length);
780
781         RegionElement->Address      = BaseAddress;
782         RegionElement->Length       = Length;
783         RegionElement->SpaceId      = SpaceId;
784         RegionElement->NextRegion   = NULL;
785
786         /*
787          * Increment the number of regions and put this one
788          * at the head of the list as it will probably get accessed
789          * more often anyway.
790          */
791         AeRegions.NumberOfRegions += 1;
792
793         if (AeRegions.RegionList)
794         {
795             RegionElement->NextRegion = AeRegions.RegionList;
796         }
797
798         AeRegions.RegionList = RegionElement;
799     }
800
801     /* Calculate the size of the memory copy */
802
803     ByteWidth = (BitWidth / 8);
804
805     if (BitWidth % 8)
806     {
807         ByteWidth += 1;
808     }
809
810     /*
811      * The buffer exists and is pointed to by RegionElement.
812      * We now need to verify the request is valid and perform the operation.
813      *
814      * NOTE: RegionElement->Length is in bytes, therefore it we compare against
815      * ByteWidth (see above)
816      */
817     if ((RegionObject->Region.SpaceId != ACPI_ADR_SPACE_GPIO) &&
818         ((UINT64) Address + ByteWidth) >
819         ((UINT64)(RegionElement->Address) + RegionElement->Length))
820     {
821         ACPI_WARNING ((AE_INFO,
822             "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X",
823             (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address,
824             ByteWidth, (UINT32)(RegionElement->Address),
825             RegionElement->Length));
826
827         return (AE_AML_REGION_LIMIT);
828     }
829
830     /*
831      * Get BufferValue to point to the "address" in the buffer
832      */
833     BufferValue = ((UINT8 *) RegionElement->Buffer +
834                     ((UINT64) Address - (UINT64) RegionElement->Address));
835
836 DoFunction:
837     /*
838      * Perform a read or write to the buffer space
839      */
840     switch (Function)
841     {
842     case ACPI_READ:
843         /*
844          * Set the pointer Value to whatever is in the buffer
845          */
846         ACPI_MEMCPY (Value, BufferValue, ByteWidth);
847         break;
848
849     case ACPI_WRITE:
850         /*
851          * Write the contents of Value to the buffer
852          */
853         ACPI_MEMCPY (BufferValue, Value, ByteWidth);
854         break;
855
856     default:
857
858         return (AE_BAD_PARAMETER);
859     }
860
861     if (AcpiGbl_DisplayRegionAccess)
862     {
863         switch (SpaceId)
864         {
865         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
866
867             AcpiOsPrintf ("AcpiExec: SystemMemory "
868                 "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n",
869                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
870                 (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length);
871             break;
872
873         case ACPI_ADR_SPACE_GPIO:   /* ACPI 5.0 */
874
875             /* This space is required to always be ByteAcc */
876
877             Status = AcpiBufferToResource (MyContext->Connection,
878                 MyContext->Length, &Resource);
879
880             AcpiOsPrintf ("AcpiExec: GeneralPurposeIo "
881                 "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n",
882                 (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value,
883                 (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth,
884                 MyContext->AccessLength, MyContext->Connection);
885             break;
886
887         default:
888
889             break;
890         }
891     }
892
893     return (AE_OK);
894 }