1280ff6e646e88238d784f2e9d18d737c535f547
[dragonfly.git] / sys / contrib / dev / acpica / source / tools / acpiexec / aehandlers.c
1 /******************************************************************************
2  *
3  * Module Name: aehandlers - Various handlers for acpiexec
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, 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    ("aehandlers")
48
49 /* Local prototypes */
50
51 static void
52 AeNotifyHandler1 (
53     ACPI_HANDLE             Device,
54     UINT32                  Value,
55     void                    *Context);
56
57 static void
58 AeNotifyHandler2 (
59     ACPI_HANDLE             Device,
60     UINT32                  Value,
61     void                    *Context);
62
63 static void
64 AeCommonNotifyHandler (
65     ACPI_HANDLE             Device,
66     UINT32                  Value,
67     UINT32                  HandlerId);
68
69 static void
70 AeDeviceNotifyHandler (
71     ACPI_HANDLE             Device,
72     UINT32                  Value,
73     void                    *Context);
74
75 static ACPI_STATUS
76 AeExceptionHandler (
77     ACPI_STATUS             AmlStatus,
78     ACPI_NAME               Name,
79     UINT16                  Opcode,
80     UINT32                  AmlOffset,
81     void                    *Context);
82
83 static ACPI_STATUS
84 AeTableHandler (
85     UINT32                  Event,
86     void                    *Table,
87     void                    *Context);
88
89 static ACPI_STATUS
90 AeRegionInit (
91     ACPI_HANDLE             RegionHandle,
92     UINT32                  Function,
93     void                    *HandlerContext,
94     void                    **RegionContext);
95
96 static void
97 AeAttachedDataHandler (
98     ACPI_HANDLE             Object,
99     void                    *Data);
100
101 static void
102 AeAttachedDataHandler2 (
103     ACPI_HANDLE             Object,
104     void                    *Data);
105
106 static UINT32
107 AeInterfaceHandler (
108     ACPI_STRING             InterfaceName,
109     UINT32                  Supported);
110
111 static ACPI_STATUS
112 AeInstallEcHandler (
113     ACPI_HANDLE             ObjHandle,
114     UINT32                  Level,
115     void                    *Context,
116     void                    **ReturnValue);
117
118 static ACPI_STATUS
119 AeInstallPciHandler (
120     ACPI_HANDLE             ObjHandle,
121     UINT32                  Level,
122     void                    *Context,
123     void                    **ReturnValue);
124
125 static ACPI_STATUS
126 AeInstallDeviceHandlers (
127     void);
128
129 #if (!ACPI_REDUCED_HARDWARE)
130 static UINT32
131 AeEventHandler (
132     void                    *Context);
133
134 static UINT32
135 AeSciHandler (
136     void                    *Context);
137
138 static char                *TableEvents[] =
139 {
140     "LOAD",
141     "UNLOAD",
142     "UNKNOWN"
143 };
144 #endif /* !ACPI_REDUCED_HARDWARE */
145
146
147 static UINT32               SigintCount = 0;
148 static AE_DEBUG_REGIONS     AeRegions;
149 BOOLEAN                     AcpiGbl_DisplayRegionAccess = FALSE;
150
151 /*
152  * We will override some of the default region handlers, especially
153  * the SystemMemory handler, which must be implemented locally.
154  * These handlers are installed "early" - before any _REG methods
155  * are executed - since they are special in the sense that the ACPI spec
156  * declares that they must "always be available". Cannot override the
157  * DataTable region handler either -- needed for test execution.
158  *
159  * NOTE: The local region handler will simulate access to these address
160  * spaces by creating a memory buffer behind each operation region.
161  */
162 static ACPI_ADR_SPACE_TYPE  DefaultSpaceIdList[] =
163 {
164     ACPI_ADR_SPACE_SYSTEM_MEMORY,
165     ACPI_ADR_SPACE_SYSTEM_IO,
166     ACPI_ADR_SPACE_PCI_CONFIG,
167     ACPI_ADR_SPACE_EC
168 };
169
170 /*
171  * We will install handlers for some of the various address space IDs.
172  * Test one user-defined address space (used by aslts).
173  */
174 #define ACPI_ADR_SPACE_USER_DEFINED1        0x80
175 #define ACPI_ADR_SPACE_USER_DEFINED2        0xE4
176
177 static ACPI_ADR_SPACE_TYPE  SpaceIdList[] =
178 {
179     ACPI_ADR_SPACE_SMBUS,
180     ACPI_ADR_SPACE_CMOS,
181     ACPI_ADR_SPACE_PCI_BAR_TARGET,
182     ACPI_ADR_SPACE_IPMI,
183     ACPI_ADR_SPACE_GPIO,
184     ACPI_ADR_SPACE_GSBUS,
185     ACPI_ADR_SPACE_FIXED_HARDWARE,
186     ACPI_ADR_SPACE_USER_DEFINED1,
187     ACPI_ADR_SPACE_USER_DEFINED2
188 };
189
190 static ACPI_CONNECTION_INFO   AeMyContext;
191
192
193 /******************************************************************************
194  *
195  * FUNCTION:    AeCtrlCHandler
196  *
197  * PARAMETERS:  Sig
198  *
199  * RETURN:      none
200  *
201  * DESCRIPTION: Control-C handler. Abort running control method if any.
202  *
203  *****************************************************************************/
204
205 void ACPI_SYSTEM_XFACE
206 AeCtrlCHandler (
207     int                     Sig)
208 {
209
210     signal (SIGINT, SIG_IGN);
211     SigintCount++;
212
213     AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount);
214
215     if (AcpiGbl_MethodExecuting)
216     {
217         AcpiGbl_AbortMethod = TRUE;
218         signal (SIGINT, AeCtrlCHandler);
219
220         if (SigintCount < 10)
221         {
222             return;
223         }
224     }
225
226     (void) AcpiOsTerminate ();
227     exit (0);
228 }
229
230
231 /******************************************************************************
232  *
233  * FUNCTION:    AeNotifyHandler(s)
234  *
235  * PARAMETERS:  Standard notify handler parameters
236  *
237  * RETURN:      Status
238  *
239  * DESCRIPTION: Notify handlers for AcpiExec utility. Used by the ASL
240  *              test suite(s) to communicate errors and other information to
241  *              this utility via the Notify() operator. Tests notify handling
242  *              and multiple notify handler support.
243  *
244  *****************************************************************************/
245
246 static void
247 AeNotifyHandler1 (
248     ACPI_HANDLE             Device,
249     UINT32                  Value,
250     void                    *Context)
251 {
252     AeCommonNotifyHandler (Device, Value, 1);
253 }
254
255 static void
256 AeNotifyHandler2 (
257     ACPI_HANDLE             Device,
258     UINT32                  Value,
259     void                    *Context)
260 {
261     AeCommonNotifyHandler (Device, Value, 2);
262 }
263
264 static void
265 AeCommonNotifyHandler (
266     ACPI_HANDLE             Device,
267     UINT32                  Value,
268     UINT32                  HandlerId)
269 {
270     char                    *Type;
271
272
273     Type = "Device";
274     if (Value <= ACPI_MAX_SYS_NOTIFY)
275     {
276         Type = "System";
277     }
278
279     switch (Value)
280     {
281 #if 0
282     case 0:
283
284         printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value);
285         if (AcpiGbl_DebugFile)
286         {
287             AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n");
288         }
289         break;
290
291     case 1:
292
293         printf ("[AcpiExec] Method Error: Incorrect numeric result\n");
294         if (AcpiGbl_DebugFile)
295         {
296             AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n");
297         }
298         break;
299
300     case 2:
301
302         printf ("[AcpiExec] Method Error: An operand was overwritten\n");
303         if (AcpiGbl_DebugFile)
304         {
305             AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n");
306         }
307         break;
308
309 #endif
310
311     default:
312
313         printf ("[AcpiExec] Handler %u: Received a %s Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
314             HandlerId, Type, AcpiUtGetNodeName (Device), Device, Value,
315             AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY));
316         if (AcpiGbl_DebugFile)
317         {
318             AcpiOsPrintf ("[AcpiExec] Handler %u: Received a %s notify, Value 0x%2.2X\n",
319                 HandlerId, Type, Value);
320         }
321
322         (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
323         break;
324     }
325 }
326
327
328 /******************************************************************************
329  *
330  * FUNCTION:    AeSystemNotifyHandler
331  *
332  * PARAMETERS:  Standard notify handler parameters
333  *
334  * RETURN:      Status
335  *
336  * DESCRIPTION: System notify handler for AcpiExec utility. Used by the ASL
337  *              test suite(s) to communicate errors and other information to
338  *              this utility via the Notify() operator.
339  *
340  *****************************************************************************/
341
342 static void
343 AeSystemNotifyHandler (
344     ACPI_HANDLE                 Device,
345     UINT32                      Value,
346     void                        *Context)
347 {
348
349     printf ("[AcpiExec] Global:    Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
350         AcpiUtGetNodeName (Device), Device, Value,
351         AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY));
352     if (AcpiGbl_DebugFile)
353     {
354         AcpiOsPrintf ("[AcpiExec] Global:    Received a System Notify, Value 0x%2.2X\n", Value);
355     }
356
357     (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
358 }
359
360
361 /******************************************************************************
362  *
363  * FUNCTION:    AeDeviceNotifyHandler
364  *
365  * PARAMETERS:  Standard notify handler parameters
366  *
367  * RETURN:      Status
368  *
369  * DESCRIPTION: Device notify handler for AcpiExec utility. Used by the ASL
370  *              test suite(s) to communicate errors and other information to
371  *              this utility via the Notify() operator.
372  *
373  *****************************************************************************/
374
375 static void
376 AeDeviceNotifyHandler (
377     ACPI_HANDLE                 Device,
378     UINT32                      Value,
379     void                        *Context)
380 {
381
382     printf ("[AcpiExec] Global:    Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
383         AcpiUtGetNodeName (Device), Device, Value,
384         AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY));
385     if (AcpiGbl_DebugFile)
386     {
387         AcpiOsPrintf ("[AcpiExec] Global:    Received a Device Notify, Value 0x%2.2X\n", Value);
388     }
389
390     (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
391 }
392
393
394 /******************************************************************************
395  *
396  * FUNCTION:    AeExceptionHandler
397  *
398  * PARAMETERS:  Standard exception handler parameters
399  *
400  * RETURN:      Status
401  *
402  * DESCRIPTION: System exception handler for AcpiExec utility.
403  *
404  *****************************************************************************/
405
406 static ACPI_STATUS
407 AeExceptionHandler (
408     ACPI_STATUS             AmlStatus,
409     ACPI_NAME               Name,
410     UINT16                  Opcode,
411     UINT32                  AmlOffset,
412     void                    *Context)
413 {
414     ACPI_STATUS             NewAmlStatus = AmlStatus;
415     ACPI_STATUS             Status;
416     ACPI_BUFFER             ReturnObj;
417     ACPI_OBJECT_LIST        ArgList;
418     ACPI_OBJECT             Arg[3];
419     const char              *Exception;
420
421
422     Exception = AcpiFormatException (AmlStatus);
423     AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception);
424     if (Name)
425     {
426         AcpiOsPrintf ("of method [%4.4s]", (char *) &Name);
427     }
428     else
429     {
430         AcpiOsPrintf ("at module level (table load)");
431     }
432     AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset);
433
434     /*
435      * Invoke the _ERR method if present
436      *
437      * Setup parameter object
438      */
439     ArgList.Count = 3;
440     ArgList.Pointer = Arg;
441
442     Arg[0].Type = ACPI_TYPE_INTEGER;
443     Arg[0].Integer.Value = AmlStatus;
444
445     Arg[1].Type = ACPI_TYPE_STRING;
446     Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
447     Arg[1].String.Length = ACPI_STRLEN (Exception);
448
449     Arg[2].Type = ACPI_TYPE_INTEGER;
450     Arg[2].Integer.Value = AcpiOsGetThreadId();
451
452     /* Setup return buffer */
453
454     ReturnObj.Pointer = NULL;
455     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
456
457     Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj);
458     if (ACPI_SUCCESS (Status))
459     {
460         if (ReturnObj.Pointer)
461         {
462             /* Override original status */
463
464             NewAmlStatus = (ACPI_STATUS)
465                 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
466
467             /* Free a buffer created via ACPI_ALLOCATE_BUFFER */
468
469             AcpiOsFree (ReturnObj.Pointer);
470         }
471     }
472     else if (Status != AE_NOT_FOUND)
473     {
474         AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n",
475             AcpiFormatException (Status));
476     }
477
478     /* Global override */
479
480     if (AcpiGbl_IgnoreErrors)
481     {
482         NewAmlStatus = AE_OK;
483     }
484
485     if (NewAmlStatus != AmlStatus)
486     {
487         AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n",
488             AcpiFormatException (NewAmlStatus));
489     }
490
491     return (NewAmlStatus);
492 }
493
494
495 /******************************************************************************
496  *
497  * FUNCTION:    AeTableHandler
498  *
499  * PARAMETERS:  Table handler
500  *
501  * RETURN:      Status
502  *
503  * DESCRIPTION: System table handler for AcpiExec utility.
504  *
505  *****************************************************************************/
506
507 static ACPI_STATUS
508 AeTableHandler (
509     UINT32                  Event,
510     void                    *Table,
511     void                    *Context)
512 {
513 #if (!ACPI_REDUCED_HARDWARE)
514     ACPI_STATUS             Status;
515 #endif /* !ACPI_REDUCED_HARDWARE */
516
517
518     if (Event > ACPI_NUM_TABLE_EVENTS)
519     {
520         Event = ACPI_NUM_TABLE_EVENTS;
521     }
522
523 #if (!ACPI_REDUCED_HARDWARE)
524     /* Enable any GPEs associated with newly-loaded GPE methods */
525
526     Status = AcpiUpdateAllGpes ();
527     AE_CHECK_OK (AcpiUpdateAllGpes, Status);
528
529     printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n",
530         TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table);
531 #endif /* !ACPI_REDUCED_HARDWARE */
532
533     return (AE_OK);
534 }
535
536
537 /******************************************************************************
538  *
539  * FUNCTION:    AeGpeHandler
540  *
541  * DESCRIPTION: Common GPE handler for acpiexec
542  *
543  *****************************************************************************/
544
545 UINT32
546 AeGpeHandler (
547     ACPI_HANDLE             GpeDevice,
548     UINT32                  GpeNumber,
549     void                    *Context)
550 {
551     ACPI_NAMESPACE_NODE     *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice;
552
553
554     AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE %02X (GPE block %4.4s)\n",
555         GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT");
556
557     return (ACPI_REENABLE_GPE);
558 }
559
560
561 /******************************************************************************
562  *
563  * FUNCTION:    AeGlobalEventHandler
564  *
565  * DESCRIPTION: Global GPE/Fixed event handler
566  *
567  *****************************************************************************/
568
569 void
570 AeGlobalEventHandler (
571     UINT32                  Type,
572     ACPI_HANDLE             Device,
573     UINT32                  EventNumber,
574     void                    *Context)
575 {
576     char                    *TypeName;
577
578
579     switch (Type)
580     {
581     case ACPI_EVENT_TYPE_GPE:
582
583         TypeName = "GPE";
584         break;
585
586     case ACPI_EVENT_TYPE_FIXED:
587
588         TypeName = "FixedEvent";
589         break;
590
591     default:
592
593         TypeName = "UNKNOWN";
594         break;
595     }
596
597     AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n",
598         TypeName, EventNumber, Device);
599 }
600
601
602 /******************************************************************************
603  *
604  * FUNCTION:    AeAttachedDataHandler
605  *
606  * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
607  *              AcpiAttachData)
608  *
609  *****************************************************************************/
610
611 static void
612 AeAttachedDataHandler (
613     ACPI_HANDLE             Object,
614     void                    *Data)
615 {
616     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
617
618
619     AcpiOsPrintf ("Received an attached data deletion (1) on %4.4s\n",
620         Node->Name.Ascii);
621 }
622
623
624 /******************************************************************************
625  *
626  * FUNCTION:    AeAttachedDataHandler2
627  *
628  * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
629  *              AcpiAttachData)
630  *
631  *****************************************************************************/
632
633 static void
634 AeAttachedDataHandler2 (
635     ACPI_HANDLE             Object,
636     void                    *Data)
637 {
638     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
639
640
641     AcpiOsPrintf ("Received an attached data deletion (2) on %4.4s\n",
642         Node->Name.Ascii);
643 }
644
645
646 /******************************************************************************
647  *
648  * FUNCTION:    AeInterfaceHandler
649  *
650  * DESCRIPTION: Handler for _OSI invocations
651  *
652  *****************************************************************************/
653
654 static UINT32
655 AeInterfaceHandler (
656     ACPI_STRING             InterfaceName,
657     UINT32                  Supported)
658 {
659     ACPI_FUNCTION_NAME (AeInterfaceHandler);
660
661
662     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
663         "Received _OSI (\"%s\"), is %ssupported\n",
664         InterfaceName, Supported == 0 ? "not " : ""));
665
666     return (Supported);
667 }
668
669
670 #if (!ACPI_REDUCED_HARDWARE)
671 /******************************************************************************
672  *
673  * FUNCTION:    AeEventHandler, AeSciHandler
674  *
675  * DESCRIPTION: Handler for Fixed Events and SCIs
676  *
677  *****************************************************************************/
678
679 static UINT32
680 AeEventHandler (
681     void                    *Context)
682 {
683     return (0);
684 }
685
686 static UINT32
687 AeSciHandler (
688     void                    *Context)
689 {
690
691     AcpiOsPrintf ("[AcpiExec] Received an SCI at handler\n");
692     return (0);
693 }
694
695 #endif /* !ACPI_REDUCED_HARDWARE */
696
697
698 /******************************************************************************
699  *
700  * FUNCTION:    AeRegionInit
701  *
702  * PARAMETERS:  None
703  *
704  * RETURN:      Status
705  *
706  * DESCRIPTION: Opregion init function.
707  *
708  *****************************************************************************/
709
710 static ACPI_STATUS
711 AeRegionInit (
712     ACPI_HANDLE                 RegionHandle,
713     UINT32                      Function,
714     void                        *HandlerContext,
715     void                        **RegionContext)
716 {
717
718     if (Function == ACPI_REGION_DEACTIVATE)
719     {
720         *RegionContext = NULL;
721     }
722     else
723     {
724         *RegionContext = RegionHandle;
725     }
726
727     return (AE_OK);
728 }
729
730
731 /*******************************************************************************
732  *
733  * FUNCTION:    AeInstallSciHandler
734  *
735  * PARAMETERS:  None
736  *
737  * RETURN:      Status
738  *
739  * DESCRIPTION: Install handler for SCIs. Exercise the code by doing an
740  *              install/remove/install.
741  *
742  ******************************************************************************/
743
744 static ACPI_STATUS
745 AeInstallSciHandler (
746     void)
747 {
748     ACPI_STATUS             Status;
749
750
751     Status = AcpiInstallSciHandler (AeSciHandler, &AeMyContext);
752     if (ACPI_FAILURE (Status))
753     {
754         ACPI_EXCEPTION ((AE_INFO, Status,
755             "Could not install an SCI handler (1)"));
756     }
757
758     Status = AcpiRemoveSciHandler (AeSciHandler);
759     if (ACPI_FAILURE (Status))
760     {
761         ACPI_EXCEPTION ((AE_INFO, Status,
762             "Could not remove an SCI handler"));
763     }
764
765     Status = AcpiInstallSciHandler (AeSciHandler, &AeMyContext);
766     if (ACPI_FAILURE (Status))
767     {
768         ACPI_EXCEPTION ((AE_INFO, Status,
769             "Could not install an SCI handler (2)"));
770     }
771
772     return (Status);
773 }
774
775
776 /*******************************************************************************
777  *
778  * FUNCTION:    AeInstallDeviceHandlers, AeInstallEcHandler,
779  *              AeInstallPciHandler
780  *
781  * PARAMETERS:  ACPI_WALK_NAMESPACE callback
782  *
783  * RETURN:      Status
784  *
785  * DESCRIPTION: Walk entire namespace, install a handler for every EC
786  *              and PCI device found.
787  *
788  ******************************************************************************/
789
790 static ACPI_STATUS
791 AeInstallEcHandler (
792     ACPI_HANDLE             ObjHandle,
793     UINT32                  Level,
794     void                    *Context,
795     void                    **ReturnValue)
796 {
797     ACPI_STATUS             Status;
798
799
800     /* Install the handler for this EC device */
801
802     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_EC,
803         AeRegionHandler, AeRegionInit, &AeMyContext);
804     if (ACPI_FAILURE (Status))
805     {
806         ACPI_EXCEPTION ((AE_INFO, Status,
807             "Could not install an OpRegion handler for EC device (%p)",
808             ObjHandle));
809     }
810
811     return (Status);
812 }
813
814 static ACPI_STATUS
815 AeInstallPciHandler (
816     ACPI_HANDLE             ObjHandle,
817     UINT32                  Level,
818     void                    *Context,
819     void                    **ReturnValue)
820 {
821     ACPI_STATUS             Status;
822
823
824     /* Install memory and I/O handlers for the PCI device */
825
826     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_IO,
827         AeRegionHandler, AeRegionInit, &AeMyContext);
828     if (ACPI_FAILURE (Status))
829     {
830         ACPI_EXCEPTION ((AE_INFO, Status,
831             "Could not install an OpRegion handler for PCI device (%p)",
832             ObjHandle));
833     }
834
835     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_MEMORY,
836         AeRegionHandler, AeRegionInit, &AeMyContext);
837     if (ACPI_FAILURE (Status))
838     {
839         ACPI_EXCEPTION ((AE_INFO, Status,
840             "Could not install an OpRegion handler for PCI device (%p)",
841             ObjHandle));
842     }
843
844     return (AE_CTRL_TERMINATE);
845 }
846
847 static ACPI_STATUS
848 AeInstallDeviceHandlers (
849     void)
850 {
851
852     /* Find all Embedded Controller devices */
853
854     AcpiGetDevices ("PNP0C09", AeInstallEcHandler, NULL, NULL);
855
856     /* Install a PCI handler */
857
858     AcpiGetDevices ("PNP0A08", AeInstallPciHandler, NULL, NULL);
859     return (AE_OK);
860 }
861
862
863 /******************************************************************************
864  *
865  * FUNCTION:    AeInstallLateHandlers
866  *
867  * PARAMETERS:  None
868  *
869  * RETURN:      Status
870  *
871  * DESCRIPTION: Install handlers for the AcpiExec utility.
872  *
873  *****************************************************************************/
874
875 ACPI_STATUS
876 AeInstallLateHandlers (
877     void)
878 {
879     ACPI_STATUS             Status;
880     UINT32                  i;
881
882
883 #if (!ACPI_REDUCED_HARDWARE)
884     if (!AcpiGbl_ReducedHardware)
885     {
886         /* Install a user SCI handler */
887
888         Status = AeInstallSciHandler ();
889         AE_CHECK_OK (AeInstallSciHandler, Status);
890
891         /* Install some fixed event handlers */
892
893         Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AeEventHandler, NULL);
894         AE_CHECK_OK (AcpiInstallFixedEventHandler, Status);
895
896         Status = AcpiInstallFixedEventHandler (ACPI_EVENT_RTC, AeEventHandler, NULL);
897         AE_CHECK_OK (AcpiInstallFixedEventHandler, Status);
898     }
899 #endif /* !ACPI_REDUCED_HARDWARE */
900
901     AeMyContext.Connection = NULL;
902     AeMyContext.AccessLength = 0xA5;
903
904     /*
905      * We will install a handler for each EC device, directly under the EC
906      * device definition. This is unlike the other handlers which we install
907      * at the root node. Also install memory and I/O handlers at any PCI
908      * devices.
909      */
910     AeInstallDeviceHandlers ();
911
912     /*
913      * Install handlers for some of the "device driver" address spaces
914      * such as SMBus, etc.
915      */
916     for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++)
917     {
918         /* Install handler at the root object */
919
920         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
921                     SpaceIdList[i], AeRegionHandler,
922                     AeRegionInit, &AeMyContext);
923         if (ACPI_FAILURE (Status))
924         {
925             ACPI_EXCEPTION ((AE_INFO, Status,
926                 "Could not install an OpRegion handler for %s space(%u)",
927                 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i]));
928             return (Status);
929         }
930     }
931
932     return (AE_OK);
933 }
934
935
936 /******************************************************************************
937  *
938  * FUNCTION:    AeInstallEarlyHandlers
939  *
940  * PARAMETERS:  None
941  *
942  * RETURN:      Status
943  *
944  * DESCRIPTION: Install handlers for the AcpiExec utility.
945  *
946  * Notes:       Don't install handler for PCI_Config, we want to use the
947  *              default handler to exercise that code.
948  *
949  *****************************************************************************/
950
951 ACPI_STATUS
952 AeInstallEarlyHandlers (
953     void)
954 {
955     ACPI_STATUS             Status;
956     UINT32                  i;
957     ACPI_HANDLE             Handle;
958
959
960     ACPI_FUNCTION_ENTRY ();
961
962
963     Status = AcpiInstallInterfaceHandler (AeInterfaceHandler);
964     if (ACPI_FAILURE (Status))
965     {
966         printf ("Could not install interface handler, %s\n",
967             AcpiFormatException (Status));
968     }
969
970     Status = AcpiInstallTableHandler (AeTableHandler, NULL);
971     if (ACPI_FAILURE (Status))
972     {
973         printf ("Could not install table handler, %s\n",
974             AcpiFormatException (Status));
975     }
976
977     Status = AcpiInstallExceptionHandler (AeExceptionHandler);
978     if (ACPI_FAILURE (Status))
979     {
980         printf ("Could not install exception handler, %s\n",
981             AcpiFormatException (Status));
982     }
983
984     /* Install global notify handlers */
985
986     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
987         AeSystemNotifyHandler, NULL);
988     if (ACPI_FAILURE (Status))
989     {
990         printf ("Could not install a global system notify handler, %s\n",
991             AcpiFormatException (Status));
992     }
993
994     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
995         AeDeviceNotifyHandler, NULL);
996     if (ACPI_FAILURE (Status))
997     {
998         printf ("Could not install a global notify handler, %s\n",
999             AcpiFormatException (Status));
1000     }
1001
1002     Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
1003     if (ACPI_SUCCESS (Status))
1004     {
1005         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1006             AeNotifyHandler1, NULL);
1007         if (ACPI_FAILURE (Status))
1008         {
1009             printf ("Could not install a notify handler, %s\n",
1010                 AcpiFormatException (Status));
1011         }
1012
1013         Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1014             AeNotifyHandler1);
1015         if (ACPI_FAILURE (Status))
1016         {
1017             printf ("Could not remove a notify handler, %s\n",
1018                 AcpiFormatException (Status));
1019         }
1020
1021         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1022             AeNotifyHandler1, NULL);
1023         AE_CHECK_OK (AcpiInstallNotifyHandler, Status);
1024
1025         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1026             AeNotifyHandler1);
1027         AE_CHECK_OK (AcpiRemoveNotifyHandler, Status);
1028
1029 #if 0
1030         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1031             AeNotifyHandler1, NULL);
1032         if (ACPI_FAILURE (Status))
1033         {
1034             printf ("Could not install a notify handler, %s\n",
1035                 AcpiFormatException (Status));
1036         }
1037 #endif
1038
1039         /* Install two handlers for _SB_ */
1040
1041         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1042             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1043
1044         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1045             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1046
1047         /* Attempt duplicate handler installation, should fail */
1048
1049         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1050             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x77777777));
1051
1052         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
1053         AE_CHECK_OK (AcpiAttachData, Status);
1054
1055         Status = AcpiDetachData (Handle, AeAttachedDataHandler);
1056         AE_CHECK_OK (AcpiDetachData, Status);
1057
1058         /* Test attach data at the root object */
1059
1060         Status = AcpiAttachData (ACPI_ROOT_OBJECT, AeAttachedDataHandler,
1061             AcpiGbl_RootNode);
1062         AE_CHECK_OK (AcpiAttachData, Status);
1063
1064         Status = AcpiAttachData (ACPI_ROOT_OBJECT, AeAttachedDataHandler2,
1065             AcpiGbl_RootNode);
1066         AE_CHECK_OK (AcpiAttachData, Status);
1067
1068         /* Test support for multiple attaches */
1069
1070         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
1071         AE_CHECK_OK (AcpiAttachData, Status);
1072
1073         Status = AcpiAttachData (Handle, AeAttachedDataHandler2, Handle);
1074         AE_CHECK_OK (AcpiAttachData, Status);
1075     }
1076     else
1077     {
1078         printf ("No _SB_ found, %s\n", AcpiFormatException (Status));
1079     }
1080
1081
1082     Status = AcpiGetHandle (NULL, "\\_TZ.TZ1", &Handle);
1083     if (ACPI_SUCCESS (Status))
1084     {
1085         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1086             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1087
1088         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1089             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1090
1091         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1092             AeNotifyHandler1);
1093         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1094             AeNotifyHandler2);
1095
1096         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1097             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1098
1099         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1100             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1101     }
1102
1103     Status = AcpiGetHandle (NULL, "\\_PR.CPU0", &Handle);
1104     if (ACPI_SUCCESS (Status))
1105     {
1106         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1107             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1108
1109         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1110             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1111     }
1112
1113     /*
1114      * Install handlers that will override the default handlers for some of
1115      * the space IDs.
1116      */
1117     for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++)
1118     {
1119         /* Install handler at the root object */
1120
1121         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
1122                     DefaultSpaceIdList[i], AeRegionHandler,
1123                     AeRegionInit, &AeMyContext);
1124         if (ACPI_FAILURE (Status))
1125         {
1126             ACPI_EXCEPTION ((AE_INFO, Status,
1127                 "Could not install a default OpRegion handler for %s space(%u)",
1128                 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]),
1129                 DefaultSpaceIdList[i]));
1130             return (Status);
1131         }
1132     }
1133
1134     /*
1135      * Initialize the global Region Handler space
1136      * MCW 3/23/00
1137      */
1138     AeRegions.NumberOfRegions = 0;
1139     AeRegions.RegionList = NULL;
1140     return (Status);
1141 }
1142
1143
1144 /******************************************************************************
1145  *
1146  * FUNCTION:    AeRegionHandler
1147  *
1148  * PARAMETERS:  Standard region handler parameters
1149  *
1150  * RETURN:      Status
1151  *
1152  * DESCRIPTION: Test handler - Handles some dummy regions via memory that can
1153  *              be manipulated in Ring 3. Simulates actual reads and writes.
1154  *
1155  *****************************************************************************/
1156
1157 ACPI_STATUS
1158 AeRegionHandler (
1159     UINT32                  Function,
1160     ACPI_PHYSICAL_ADDRESS   Address,
1161     UINT32                  BitWidth,
1162     UINT64                  *Value,
1163     void                    *HandlerContext,
1164     void                    *RegionContext)
1165 {
1166
1167     ACPI_OPERAND_OBJECT     *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
1168     UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Value);
1169     UINT8                   *OldBuffer;
1170     UINT8                   *NewBuffer;
1171     ACPI_PHYSICAL_ADDRESS   BaseAddress;
1172     ACPI_PHYSICAL_ADDRESS   BaseAddressEnd;
1173     ACPI_PHYSICAL_ADDRESS   RegionAddress;
1174     ACPI_PHYSICAL_ADDRESS   RegionAddressEnd;
1175     ACPI_SIZE               Length;
1176     BOOLEAN                 BufferExists;
1177     BOOLEAN                 BufferResize;
1178     AE_REGION               *RegionElement;
1179     void                    *BufferValue;
1180     ACPI_STATUS             Status;
1181     UINT32                  ByteWidth;
1182     UINT32                  RegionLength;
1183     UINT32                  i;
1184     UINT8                   SpaceId;
1185     ACPI_CONNECTION_INFO    *MyContext;
1186     UINT32                  Value1;
1187     UINT32                  Value2;
1188     ACPI_RESOURCE           *Resource;
1189
1190
1191     ACPI_FUNCTION_NAME (AeRegionHandler);
1192
1193     /*
1194      * If the object is not a region, simply return
1195      */
1196     if (RegionObject->Region.Type != ACPI_TYPE_REGION)
1197     {
1198         return (AE_OK);
1199     }
1200
1201     /* Check that we actually got back our context parameter */
1202
1203     if (HandlerContext != &AeMyContext)
1204     {
1205         printf ("Region handler received incorrect context %p, should be %p\n",
1206             HandlerContext, &AeMyContext);
1207     }
1208
1209     MyContext = ACPI_CAST_PTR (ACPI_CONNECTION_INFO, HandlerContext);
1210
1211     /*
1212      * Find the region's address space and length before searching
1213      * the linked list.
1214      */
1215     BaseAddress = RegionObject->Region.Address;
1216     Length = (ACPI_SIZE) RegionObject->Region.Length;
1217     SpaceId = RegionObject->Region.SpaceId;
1218
1219     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n",
1220             AcpiUtGetRegionName (RegionObject->Region.SpaceId),
1221             (UINT32) Address));
1222
1223     /*
1224      * Region support can be disabled with the -do option.
1225      * We use this to support dynamically loaded tables where we pass a valid
1226      * address to the AML.
1227      */
1228     if (AcpiGbl_DbOpt_NoRegionSupport)
1229     {
1230         BufferValue = ACPI_TO_POINTER (Address);
1231         ByteWidth = (BitWidth / 8);
1232
1233         if (BitWidth % 8)
1234         {
1235             ByteWidth += 1;
1236         }
1237         goto DoFunction;
1238     }
1239
1240     switch (SpaceId)
1241     {
1242     case ACPI_ADR_SPACE_SYSTEM_IO:
1243         /*
1244          * For I/O space, exercise the port validation
1245          * Note: ReadPort currently always returns all ones, length=BitLength
1246          */
1247         switch (Function & ACPI_IO_MASK)
1248         {
1249         case ACPI_READ:
1250
1251             if (BitWidth == 64)
1252             {
1253                 /* Split the 64-bit request into two 32-bit requests */
1254
1255                 Status = AcpiHwReadPort (Address, &Value1, 32);
1256                 AE_CHECK_OK (AcpiHwReadPort, Status);
1257                 Status = AcpiHwReadPort (Address+4, &Value2, 32);
1258                 AE_CHECK_OK (AcpiHwReadPort, Status);
1259
1260                 *Value = Value1 | ((UINT64) Value2 << 32);
1261             }
1262             else
1263             {
1264                 Status = AcpiHwReadPort (Address, &Value1, BitWidth);
1265                 AE_CHECK_OK (AcpiHwReadPort, Status);
1266                 *Value = (UINT64) Value1;
1267             }
1268             break;
1269
1270         case ACPI_WRITE:
1271
1272             if (BitWidth == 64)
1273             {
1274                 /* Split the 64-bit request into two 32-bit requests */
1275
1276                 Status = AcpiHwWritePort (Address, ACPI_LODWORD (*Value), 32);
1277                 AE_CHECK_OK (AcpiHwWritePort, Status);
1278                 Status = AcpiHwWritePort (Address+4, ACPI_HIDWORD (*Value), 32);
1279                 AE_CHECK_OK (AcpiHwWritePort, Status);
1280             }
1281             else
1282             {
1283                 Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth);
1284                 AE_CHECK_OK (AcpiHwWritePort, Status);
1285             }
1286             break;
1287
1288         default:
1289
1290             Status = AE_BAD_PARAMETER;
1291             break;
1292         }
1293
1294         if (ACPI_FAILURE (Status))
1295         {
1296             return (Status);
1297         }
1298
1299         /* Now go ahead and simulate the hardware */
1300         break;
1301
1302     /*
1303      * SMBus and GenericSerialBus support the various bidirectional
1304      * protocols.
1305      */
1306     case ACPI_ADR_SPACE_SMBUS:
1307     case ACPI_ADR_SPACE_GSBUS:  /* ACPI 5.0 */
1308
1309         Length = 0;
1310
1311         switch (Function & ACPI_IO_MASK)
1312         {
1313         case ACPI_READ:
1314
1315             switch (Function >> 16)
1316             {
1317             case AML_FIELD_ATTRIB_QUICK:
1318
1319                 Length = 0;
1320                 break;
1321
1322             case AML_FIELD_ATTRIB_SEND_RCV:
1323             case AML_FIELD_ATTRIB_BYTE:
1324
1325                 Length = 1;
1326                 break;
1327
1328             case AML_FIELD_ATTRIB_WORD:
1329             case AML_FIELD_ATTRIB_WORD_CALL:
1330
1331                 Length = 2;
1332                 break;
1333
1334             case AML_FIELD_ATTRIB_BLOCK:
1335             case AML_FIELD_ATTRIB_BLOCK_CALL:
1336
1337                 Length = 32;
1338                 break;
1339
1340             case AML_FIELD_ATTRIB_MULTIBYTE:
1341             case AML_FIELD_ATTRIB_RAW_BYTES:
1342             case AML_FIELD_ATTRIB_RAW_PROCESS:
1343
1344                 /* (-2) for status/length */
1345                 Length = MyContext->AccessLength - 2;
1346                 break;
1347
1348             default:
1349
1350                 break;
1351             }
1352             break;
1353
1354         case ACPI_WRITE:
1355
1356             switch (Function >> 16)
1357             {
1358             case AML_FIELD_ATTRIB_QUICK:
1359             case AML_FIELD_ATTRIB_SEND_RCV:
1360             case AML_FIELD_ATTRIB_BYTE:
1361             case AML_FIELD_ATTRIB_WORD:
1362             case AML_FIELD_ATTRIB_BLOCK:
1363
1364                 Length = 0;
1365                 break;
1366
1367             case AML_FIELD_ATTRIB_WORD_CALL:
1368                 Length = 2;
1369                 break;
1370
1371             case AML_FIELD_ATTRIB_BLOCK_CALL:
1372                 Length = 32;
1373                 break;
1374
1375             case AML_FIELD_ATTRIB_MULTIBYTE:
1376             case AML_FIELD_ATTRIB_RAW_BYTES:
1377             case AML_FIELD_ATTRIB_RAW_PROCESS:
1378
1379                 /* (-2) for status/length */
1380                 Length = MyContext->AccessLength - 2;
1381                 break;
1382
1383             default:
1384
1385                 break;
1386             }
1387             break;
1388
1389         default:
1390
1391             break;
1392         }
1393
1394         if (AcpiGbl_DisplayRegionAccess)
1395         {
1396             AcpiOsPrintf ("AcpiExec: %s "
1397                 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X",
1398                 AcpiUtGetRegionName (SpaceId),
1399                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
1400                 (UINT32) (Function >> 16),
1401                 (UINT32) Address, (UINT32) BaseAddress,
1402                 Length, BitWidth, Buffer[1]);
1403
1404             /* GenericSerialBus has a Connection() parameter */
1405
1406             if (SpaceId == ACPI_ADR_SPACE_GSBUS)
1407             {
1408                 Status = AcpiBufferToResource (MyContext->Connection,
1409                     MyContext->Length, &Resource);
1410
1411                 AcpiOsPrintf (" [AccLen %.2X Conn %p]",
1412                     MyContext->AccessLength, MyContext->Connection);
1413             }
1414             AcpiOsPrintf ("\n");
1415         }
1416
1417         /* Setup the return buffer. Note: ASLTS depends on these fill values */
1418
1419         for (i = 0; i < Length; i++)
1420         {
1421             Buffer[i+2] = (UINT8) (0xA0 + i);
1422         }
1423
1424         Buffer[0] = 0x7A;
1425         Buffer[1] = (UINT8) Length;
1426         return (AE_OK);
1427
1428
1429     case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
1430
1431         if (AcpiGbl_DisplayRegionAccess)
1432         {
1433             AcpiOsPrintf ("AcpiExec: IPMI "
1434                 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n",
1435                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
1436                 (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress,
1437                 Length, BitWidth, Buffer[1]);
1438         }
1439
1440         /*
1441          * Regardless of a READ or WRITE, this handler is passed a 66-byte
1442          * buffer in which to return the IPMI status/length/data.
1443          *
1444          * Return some example data to show use of the bidirectional buffer
1445          */
1446         Buffer[0] = 0;       /* Status byte */
1447         Buffer[1] = 64;      /* Return buffer data length */
1448         Buffer[2] = 0;       /* Completion code */
1449         Buffer[3] = 0;       /* Reserved */
1450
1451         /*
1452          * Fill the 66-byte buffer with the return data.
1453          * Note: ASLTS depends on these fill values.
1454          */
1455         for (i = 4; i < 66; i++)
1456         {
1457             Buffer[i] = (UINT8) (i);
1458         }
1459         return (AE_OK);
1460
1461     default:
1462         break;
1463     }
1464
1465     /*
1466      * Search through the linked list for this region's buffer
1467      */
1468     BufferExists = FALSE;
1469     BufferResize = FALSE;
1470     RegionElement = AeRegions.RegionList;
1471
1472     if (AeRegions.NumberOfRegions)
1473     {
1474         BaseAddressEnd = BaseAddress + Length - 1;
1475         while (!BufferExists && RegionElement)
1476         {
1477             RegionAddress = RegionElement->Address;
1478             RegionAddressEnd = RegionElement->Address + RegionElement->Length - 1;
1479             RegionLength = RegionElement->Length;
1480
1481             /*
1482              * Overlapping Region Support
1483              *
1484              * While searching through the region buffer list, determine if an
1485              * overlap exists between the requested buffer space and the current
1486              * RegionElement space. If there is an overlap then replace the old
1487              * buffer with a new buffer of increased size before continuing to
1488              * do the read or write
1489              */
1490             if (RegionElement->SpaceId != SpaceId ||
1491                 BaseAddressEnd < RegionAddress ||
1492                 BaseAddress > RegionAddressEnd)
1493             {
1494                 /*
1495                  * Requested buffer is outside of the current RegionElement
1496                  * bounds
1497                  */
1498                 RegionElement = RegionElement->NextRegion;
1499             }
1500             else
1501             {
1502                 /*
1503                  * Some amount of buffer space sharing exists. There are 4 cases
1504                  * to consider:
1505                  *
1506                  * 1. Right overlap
1507                  * 2. Left overlap
1508                  * 3. Left and right overlap
1509                  * 4. Fully contained - no resizing required
1510                  */
1511                 BufferExists = TRUE;
1512
1513                 if ((BaseAddress >= RegionAddress) &&
1514                     (BaseAddress <= RegionAddressEnd) &&
1515                     (BaseAddressEnd > RegionAddressEnd))
1516                 {
1517                     /* Right overlap */
1518
1519                     RegionElement->Length = BaseAddress -
1520                         RegionAddress + Length;
1521                     BufferResize = TRUE;
1522                 }
1523
1524                 else if ((BaseAddressEnd >= RegionAddress) &&
1525                          (BaseAddressEnd <= RegionAddressEnd) &&
1526                          (BaseAddress < RegionAddress))
1527                 {
1528                     /* Left overlap */
1529
1530                     RegionElement->Address = BaseAddress;
1531                     RegionElement->Length = RegionAddress -
1532                         BaseAddress + RegionElement->Length;
1533                     BufferResize = TRUE;
1534                 }
1535
1536                 else if ((BaseAddress < RegionAddress) &&
1537                          (BaseAddressEnd > RegionAddressEnd))
1538                 {
1539                     /* Left and right overlap */
1540
1541                     RegionElement->Address = BaseAddress;
1542                     RegionElement->Length = Length;
1543                     BufferResize = TRUE;
1544                 }
1545
1546                 /*
1547                  * only remaining case is fully contained for which we don't
1548                  * need to do anything
1549                  */
1550                 if (BufferResize)
1551                 {
1552                     NewBuffer = AcpiOsAllocate (RegionElement->Length);
1553                     if (!NewBuffer)
1554                     {
1555                         return (AE_NO_MEMORY);
1556                     }
1557
1558                     OldBuffer = RegionElement->Buffer;
1559                     RegionElement->Buffer = NewBuffer;
1560                     NewBuffer = NULL;
1561
1562                     /* Initialize the region with the default fill value */
1563
1564                     ACPI_MEMSET (RegionElement->Buffer,
1565                         AcpiGbl_RegionFillValue, RegionElement->Length);
1566
1567                     /*
1568                      * Get BufferValue to point (within the new buffer) to the
1569                      * base address of the old buffer
1570                      */
1571                     BufferValue = (UINT8 *) RegionElement->Buffer +
1572                         (UINT64) RegionAddress -
1573                         (UINT64) RegionElement->Address;
1574
1575                     /*
1576                      * Copy the old buffer to its same location within the new
1577                      * buffer
1578                      */
1579                     ACPI_MEMCPY (BufferValue, OldBuffer, RegionLength);
1580                     AcpiOsFree (OldBuffer);
1581                 }
1582             }
1583         }
1584     }
1585
1586     /*
1587      * If the Region buffer does not exist, create it now
1588      */
1589     if (!BufferExists)
1590     {
1591         /* Do the memory allocations first */
1592
1593         RegionElement = AcpiOsAllocate (sizeof (AE_REGION));
1594         if (!RegionElement)
1595         {
1596             return (AE_NO_MEMORY);
1597         }
1598
1599         RegionElement->Buffer = AcpiOsAllocate (Length);
1600         if (!RegionElement->Buffer)
1601         {
1602             AcpiOsFree (RegionElement);
1603             return (AE_NO_MEMORY);
1604         }
1605
1606         /* Initialize the region with the default fill value */
1607
1608         ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length);
1609
1610         RegionElement->Address      = BaseAddress;
1611         RegionElement->Length       = Length;
1612         RegionElement->SpaceId      = SpaceId;
1613         RegionElement->NextRegion   = NULL;
1614
1615         /*
1616          * Increment the number of regions and put this one
1617          * at the head of the list as it will probably get accessed
1618          * more often anyway.
1619          */
1620         AeRegions.NumberOfRegions += 1;
1621
1622         if (AeRegions.RegionList)
1623         {
1624             RegionElement->NextRegion = AeRegions.RegionList;
1625         }
1626
1627         AeRegions.RegionList = RegionElement;
1628     }
1629
1630     /* Calculate the size of the memory copy */
1631
1632     ByteWidth = (BitWidth / 8);
1633
1634     if (BitWidth % 8)
1635     {
1636         ByteWidth += 1;
1637     }
1638
1639     /*
1640      * The buffer exists and is pointed to by RegionElement.
1641      * We now need to verify the request is valid and perform the operation.
1642      *
1643      * NOTE: RegionElement->Length is in bytes, therefore it we compare against
1644      * ByteWidth (see above)
1645      */
1646     if (((UINT64) Address + ByteWidth) >
1647         ((UINT64)(RegionElement->Address) + RegionElement->Length))
1648     {
1649         ACPI_WARNING ((AE_INFO,
1650             "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X",
1651             (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address,
1652             ByteWidth, (UINT32)(RegionElement->Address),
1653             RegionElement->Length));
1654
1655         return (AE_AML_REGION_LIMIT);
1656     }
1657
1658     /*
1659      * Get BufferValue to point to the "address" in the buffer
1660      */
1661     BufferValue = ((UINT8 *) RegionElement->Buffer +
1662                     ((UINT64) Address - (UINT64) RegionElement->Address));
1663
1664 DoFunction:
1665     /*
1666      * Perform a read or write to the buffer space
1667      */
1668     switch (Function)
1669     {
1670     case ACPI_READ:
1671         /*
1672          * Set the pointer Value to whatever is in the buffer
1673          */
1674         ACPI_MEMCPY (Value, BufferValue, ByteWidth);
1675         break;
1676
1677     case ACPI_WRITE:
1678         /*
1679          * Write the contents of Value to the buffer
1680          */
1681         ACPI_MEMCPY (BufferValue, Value, ByteWidth);
1682         break;
1683
1684     default:
1685
1686         return (AE_BAD_PARAMETER);
1687     }
1688
1689     if (AcpiGbl_DisplayRegionAccess)
1690     {
1691         switch (SpaceId)
1692         {
1693         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1694
1695             AcpiOsPrintf ("AcpiExec: SystemMemory "
1696                 "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n",
1697                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
1698                 (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length);
1699             break;
1700
1701         case ACPI_ADR_SPACE_GPIO:   /* ACPI 5.0 */
1702
1703             /* This space is required to always be ByteAcc */
1704
1705             Status = AcpiBufferToResource (MyContext->Connection,
1706                 MyContext->Length, &Resource);
1707
1708             AcpiOsPrintf ("AcpiExec: GeneralPurposeIo "
1709                 "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n",
1710                 (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value,
1711                 (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth,
1712                 MyContext->AccessLength, MyContext->Connection);
1713             break;
1714
1715         default:
1716
1717             break;
1718         }
1719     }
1720
1721     return (AE_OK);
1722 }