xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpiexec/aehandlers.c (revision aceb213538ec08a74028e213127af18aa17bf1cf)
1 /******************************************************************************
2  *
3  * Module Name: aehandlers - Various handlers for acpiexec
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, 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 AeNotifyHandler (
53     ACPI_HANDLE             Device,
54     UINT32                  Value,
55     void                    *Context);
56 
57 static void
58 AeDeviceNotifyHandler (
59     ACPI_HANDLE             Device,
60     UINT32                  Value,
61     void                    *Context);
62 
63 static ACPI_STATUS
64 AeExceptionHandler (
65     ACPI_STATUS             AmlStatus,
66     ACPI_NAME               Name,
67     UINT16                  Opcode,
68     UINT32                  AmlOffset,
69     void                    *Context);
70 
71 static ACPI_STATUS
72 AeTableHandler (
73     UINT32                  Event,
74     void                    *Table,
75     void                    *Context);
76 
77 static ACPI_STATUS
78 AeRegionInit (
79     ACPI_HANDLE             RegionHandle,
80     UINT32                  Function,
81     void                    *HandlerContext,
82     void                    **RegionContext);
83 
84 static void
85 AeAttachedDataHandler (
86     ACPI_HANDLE             Object,
87     void                    *Data);
88 
89 static UINT32
90 AeInterfaceHandler (
91     ACPI_STRING             InterfaceName,
92     UINT32                  Supported);
93 
94 static UINT32
95 AeEventHandler (
96     void                    *Context);
97 
98 static UINT32               SigintCount = 0;
99 static AE_DEBUG_REGIONS     AeRegions;
100 
101 
102 /*
103  * We will override some of the default region handlers, especially the
104  * SystemMemory handler, which must be implemented locally. Do not override
105  * the PCI_Config handler since we would like to exercise the default handler
106  * code. These handlers are installed "early" - before any _REG methods
107  * are executed - since they are special in the sense that tha ACPI spec
108  * declares that they must "always be available". Cannot override the
109  * DataTable region handler either -- needed for test execution.
110  */
111 static ACPI_ADR_SPACE_TYPE  DefaultSpaceIdList[] = {
112     ACPI_ADR_SPACE_SYSTEM_MEMORY,
113     ACPI_ADR_SPACE_SYSTEM_IO
114 };
115 
116 /*
117  * We will install handlers for some of the various address space IDs
118  * Test one user-defined address space (used by aslts.)
119  */
120 #define ACPI_ADR_SPACE_USER_DEFINED     0x80
121 
122 static ACPI_ADR_SPACE_TYPE  SpaceIdList[] = {
123     ACPI_ADR_SPACE_EC,
124     ACPI_ADR_SPACE_SMBUS,
125     ACPI_ADR_SPACE_PCI_BAR_TARGET,
126     ACPI_ADR_SPACE_IPMI,
127     ACPI_ADR_SPACE_FIXED_HARDWARE,
128     ACPI_ADR_SPACE_USER_DEFINED
129 };
130 
131 
132 /******************************************************************************
133  *
134  * FUNCTION:    AeCtrlCHandler
135  *
136  * PARAMETERS:  Sig
137  *
138  * RETURN:      none
139  *
140  * DESCRIPTION: Control-C handler.  Abort running control method if any.
141  *
142  *****************************************************************************/
143 
144 void ACPI_SYSTEM_XFACE
145 AeCtrlCHandler (
146     int                     Sig)
147 {
148 
149     signal (SIGINT, SIG_IGN);
150     SigintCount++;
151 
152     AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount);
153 
154     if (AcpiGbl_MethodExecuting)
155     {
156         AcpiGbl_AbortMethod = TRUE;
157         signal (SIGINT, AeCtrlCHandler);
158 
159         if (SigintCount < 10)
160         {
161             return;
162         }
163     }
164 
165     exit (0);
166 }
167 
168 
169 /******************************************************************************
170  *
171  * FUNCTION:    AeNotifyHandler
172  *
173  * PARAMETERS:  Standard notify handler parameters
174  *
175  * RETURN:      Status
176  *
177  * DESCRIPTION: System notify handler for AcpiExec utility.  Used by the ASL
178  *              test suite(s) to communicate errors and other information to
179  *              this utility via the Notify() operator.
180  *
181  *****************************************************************************/
182 
183 static void
184 AeNotifyHandler (
185     ACPI_HANDLE                 Device,
186     UINT32                      Value,
187     void                        *Context)
188 {
189 
190     switch (Value)
191     {
192 #if 0
193     case 0:
194         printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value);
195         if (AcpiGbl_DebugFile)
196         {
197             AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n");
198         }
199         break;
200 
201 
202     case 1:
203         printf ("[AcpiExec] Method Error: Incorrect numeric result\n");
204         if (AcpiGbl_DebugFile)
205         {
206             AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n");
207         }
208         break;
209 
210 
211     case 2:
212         printf ("[AcpiExec] Method Error: An operand was overwritten\n");
213         if (AcpiGbl_DebugFile)
214         {
215             AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n");
216         }
217         break;
218 
219 #endif
220 
221     default:
222         printf ("[AcpiExec] Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
223             AcpiUtGetNodeName (Device), Device, Value,
224             AcpiUtGetNotifyName (Value));
225         if (AcpiGbl_DebugFile)
226         {
227             AcpiOsPrintf ("[AcpiExec] Received a system notify, Value 0x%2.2X\n", Value);
228         }
229 
230         (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
231         break;
232     }
233 }
234 
235 
236 /******************************************************************************
237  *
238  * FUNCTION:    AeDeviceNotifyHandler
239  *
240  * PARAMETERS:  Standard notify handler parameters
241  *
242  * RETURN:      Status
243  *
244  * DESCRIPTION: Device notify handler for AcpiExec utility.  Used by the ASL
245  *              test suite(s) to communicate errors and other information to
246  *              this utility via the Notify() operator.
247  *
248  *****************************************************************************/
249 
250 static void
251 AeDeviceNotifyHandler (
252     ACPI_HANDLE                 Device,
253     UINT32                      Value,
254     void                        *Context)
255 {
256 
257     printf ("[AcpiExec] Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
258         AcpiUtGetNodeName (Device), Device, Value,
259         AcpiUtGetNotifyName (Value));
260     if (AcpiGbl_DebugFile)
261     {
262         AcpiOsPrintf ("[AcpiExec] Received a device notify, Value 0x%2.2X\n", Value);
263     }
264 
265     (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
266 }
267 
268 
269 /******************************************************************************
270  *
271  * FUNCTION:    AeExceptionHandler
272  *
273  * PARAMETERS:  Standard exception handler parameters
274  *
275  * RETURN:      Status
276  *
277  * DESCRIPTION: System exception handler for AcpiExec utility.
278  *
279  *****************************************************************************/
280 
281 static ACPI_STATUS
282 AeExceptionHandler (
283     ACPI_STATUS             AmlStatus,
284     ACPI_NAME               Name,
285     UINT16                  Opcode,
286     UINT32                  AmlOffset,
287     void                    *Context)
288 {
289     ACPI_STATUS             NewAmlStatus = AmlStatus;
290     ACPI_STATUS             Status;
291     ACPI_BUFFER             ReturnObj;
292     ACPI_OBJECT_LIST        ArgList;
293     ACPI_OBJECT             Arg[3];
294     const char              *Exception;
295 
296 
297     Exception = AcpiFormatException (AmlStatus);
298     AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception);
299     if (Name)
300     {
301         AcpiOsPrintf ("of method [%4.4s]", (char *) &Name);
302     }
303     else
304     {
305         AcpiOsPrintf ("at module level (table load)");
306     }
307     AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset);
308 
309     /*
310      * Invoke the _ERR method if present
311      *
312      * Setup parameter object
313      */
314     ArgList.Count = 3;
315     ArgList.Pointer = Arg;
316 
317     Arg[0].Type = ACPI_TYPE_INTEGER;
318     Arg[0].Integer.Value = AmlStatus;
319 
320     Arg[1].Type = ACPI_TYPE_STRING;
321     Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
322     Arg[1].String.Length = ACPI_STRLEN (Exception);
323 
324     Arg[2].Type = ACPI_TYPE_INTEGER;
325     Arg[2].Integer.Value = AcpiOsGetThreadId();
326 
327     /* Setup return buffer */
328 
329     ReturnObj.Pointer = NULL;
330     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
331 
332     Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj);
333     if (ACPI_SUCCESS (Status))
334     {
335         if (ReturnObj.Pointer)
336         {
337             /* Override original status */
338 
339             NewAmlStatus = (ACPI_STATUS)
340                 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
341 
342             AcpiOsFree (ReturnObj.Pointer);
343         }
344     }
345     else if (Status != AE_NOT_FOUND)
346     {
347         AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n",
348             AcpiFormatException (Status));
349     }
350 
351     /* Global override */
352 
353     if (AcpiGbl_IgnoreErrors)
354     {
355         NewAmlStatus = AE_OK;
356     }
357 
358     if (NewAmlStatus != AmlStatus)
359     {
360         AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n",
361             AcpiFormatException (NewAmlStatus));
362     }
363 
364     return (NewAmlStatus);
365 }
366 
367 
368 /******************************************************************************
369  *
370  * FUNCTION:    AeTableHandler
371  *
372  * PARAMETERS:  Table handler
373  *
374  * RETURN:      Status
375  *
376  * DESCRIPTION: System table handler for AcpiExec utility.
377  *
378  *****************************************************************************/
379 
380 static char                *TableEvents[] =
381 {
382     "LOAD",
383     "UNLOAD",
384     "UNKNOWN"
385 };
386 
387 static ACPI_STATUS
388 AeTableHandler (
389     UINT32                  Event,
390     void                    *Table,
391     void                    *Context)
392 {
393     ACPI_STATUS             Status;
394 
395 
396     if (Event > ACPI_NUM_TABLE_EVENTS)
397     {
398         Event = ACPI_NUM_TABLE_EVENTS;
399     }
400 
401     /* Enable any GPEs associated with newly-loaded GPE methods */
402 
403     Status = AcpiUpdateAllGpes ();
404     AE_CHECK_OK (AcpiUpdateAllGpes, Status);
405 
406     printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n",
407         TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table);
408     return (AE_OK);
409 }
410 
411 
412 /******************************************************************************
413  *
414  * FUNCTION:    AeGpeHandler
415  *
416  * DESCRIPTION: Common GPE handler for acpiexec
417  *
418  *****************************************************************************/
419 
420 UINT32
421 AeGpeHandler (
422     ACPI_HANDLE             GpeDevice,
423     UINT32                  GpeNumber,
424     void                    *Context)
425 {
426     ACPI_NAMESPACE_NODE     *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice;
427 
428 
429     AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE%02X (GPE block %4.4s)\n",
430         GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT");
431 
432     return (ACPI_REENABLE_GPE);
433 }
434 
435 
436 /******************************************************************************
437  *
438  * FUNCTION:    AeGlobalEventHandler
439  *
440  * DESCRIPTION: Global GPE/Fixed event handler
441  *
442  *****************************************************************************/
443 
444 void
445 AeGlobalEventHandler (
446     UINT32                  Type,
447     ACPI_HANDLE             Device,
448     UINT32                  EventNumber,
449     void                    *Context)
450 {
451     char                    *TypeName;
452 
453 
454     switch (Type)
455     {
456     case ACPI_EVENT_TYPE_GPE:
457         TypeName = "GPE";
458         break;
459 
460     case ACPI_EVENT_TYPE_FIXED:
461         TypeName = "FixedEvent";
462         break;
463 
464     default:
465         TypeName = "UNKNOWN";
466         break;
467     }
468 
469     AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n",
470         TypeName, EventNumber, Device);
471 }
472 
473 
474 /******************************************************************************
475  *
476  * FUNCTION:    AeAttachedDataHandler
477  *
478  * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
479  *              AcpiAttachData)
480  *
481  *****************************************************************************/
482 
483 static void
484 AeAttachedDataHandler (
485     ACPI_HANDLE             Object,
486     void                    *Data)
487 {
488     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
489 
490 
491     AcpiOsPrintf ("Received an attached data deletion on %4.4s\n",
492         Node->Name.Ascii);
493 }
494 
495 
496 /******************************************************************************
497  *
498  * FUNCTION:    AeInterfaceHandler
499  *
500  * DESCRIPTION: Handler for _OSI invocations
501  *
502  *****************************************************************************/
503 
504 static UINT32
505 AeInterfaceHandler (
506     ACPI_STRING             InterfaceName,
507     UINT32                  Supported)
508 {
509     ACPI_FUNCTION_NAME (AeInterfaceHandler);
510 
511 
512     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
513         "Received _OSI (\"%s\"), is %ssupported\n",
514         InterfaceName, Supported == 0 ? "not " : ""));
515 
516     return (Supported);
517 }
518 
519 
520 /******************************************************************************
521  *
522  * FUNCTION:    AeEventHandler
523  *
524  * DESCRIPTION: Handler for Fixed Events
525  *
526  *****************************************************************************/
527 
528 static UINT32
529 AeEventHandler (
530     void                    *Context)
531 {
532     return (0);
533 }
534 
535 
536 /******************************************************************************
537  *
538  * FUNCTION:    AeRegionInit
539  *
540  * PARAMETERS:  None
541  *
542  * RETURN:      Status
543  *
544  * DESCRIPTION: Opregion init function.
545  *
546  *****************************************************************************/
547 
548 static ACPI_STATUS
549 AeRegionInit (
550     ACPI_HANDLE                 RegionHandle,
551     UINT32                      Function,
552     void                        *HandlerContext,
553     void                        **RegionContext)
554 {
555     /*
556      * Real simple, set the RegionContext to the RegionHandle
557      */
558     *RegionContext = RegionHandle;
559 
560     return (AE_OK);
561 }
562 
563 
564 /******************************************************************************
565  *
566  * FUNCTION:    AeInstallLateHandlers
567  *
568  * PARAMETERS:  None
569  *
570  * RETURN:      Status
571  *
572  * DESCRIPTION: Install handlers for the AcpiExec utility.
573  *
574  *****************************************************************************/
575 
576 ACPI_STATUS
577 AeInstallLateHandlers (
578     void)
579 {
580     ACPI_STATUS             Status;
581     UINT32                  i;
582 
583 
584     /* Install some fixed event handlers */
585 
586     Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AeEventHandler, NULL);
587     AE_CHECK_OK (AcpiInstallFixedEventHandler, Status);
588 
589     Status = AcpiInstallFixedEventHandler (ACPI_EVENT_RTC, AeEventHandler, NULL);
590     AE_CHECK_OK (AcpiInstallFixedEventHandler, Status);
591 
592     /*
593      * Install handlers for some of the "device driver" address spaces
594      * such as EC, SMBus, etc.
595      */
596     for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++)
597     {
598         /* Install handler at the root object */
599 
600         Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode,
601                         SpaceIdList[i], AeRegionHandler, AeRegionInit, NULL);
602         if (ACPI_FAILURE (Status))
603         {
604             ACPI_EXCEPTION ((AE_INFO, Status,
605                 "Could not install an OpRegion handler for %s space(%u)",
606                 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i]));
607             return (Status);
608         }
609     }
610 
611     return (AE_OK);
612 }
613 
614 
615 /******************************************************************************
616  *
617  * FUNCTION:    AeInstallEarlyHandlers
618  *
619  * PARAMETERS:  None
620  *
621  * RETURN:      Status
622  *
623  * DESCRIPTION: Install handlers for the AcpiExec utility.
624  *
625  * Notes:       Don't install handler for PCI_Config, we want to use the
626  *              default handler to exercise that code.
627  *
628  *****************************************************************************/
629 
630 ACPI_STATUS
631 AeInstallEarlyHandlers (
632     void)
633 {
634     ACPI_STATUS             Status;
635     UINT32                  i;
636     ACPI_HANDLE             Handle;
637 
638 
639     ACPI_FUNCTION_ENTRY ();
640 
641 
642     Status = AcpiInstallInterfaceHandler (AeInterfaceHandler);
643     if (ACPI_FAILURE (Status))
644     {
645         printf ("Could not install interface handler, %s\n",
646             AcpiFormatException (Status));
647     }
648 
649     Status = AcpiInstallTableHandler (AeTableHandler, NULL);
650     if (ACPI_FAILURE (Status))
651     {
652         printf ("Could not install table handler, %s\n",
653             AcpiFormatException (Status));
654     }
655 
656     Status = AcpiInstallExceptionHandler (AeExceptionHandler);
657     if (ACPI_FAILURE (Status))
658     {
659         printf ("Could not install exception handler, %s\n",
660             AcpiFormatException (Status));
661     }
662 
663     /* Install global notify handler */
664 
665     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
666                                         AeNotifyHandler, NULL);
667     if (ACPI_FAILURE (Status))
668     {
669         printf ("Could not install a global notify handler, %s\n",
670             AcpiFormatException (Status));
671     }
672 
673     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
674                                         AeDeviceNotifyHandler, NULL);
675     if (ACPI_FAILURE (Status))
676     {
677         printf ("Could not install a global notify handler, %s\n",
678             AcpiFormatException (Status));
679     }
680 
681     Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
682     if (ACPI_SUCCESS (Status))
683     {
684         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
685                                             AeNotifyHandler, NULL);
686         if (ACPI_FAILURE (Status))
687         {
688             printf ("Could not install a notify handler, %s\n",
689                 AcpiFormatException (Status));
690         }
691 
692         Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
693                                             AeNotifyHandler);
694         if (ACPI_FAILURE (Status))
695         {
696             printf ("Could not remove a notify handler, %s\n",
697                 AcpiFormatException (Status));
698         }
699 
700         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
701                                             AeNotifyHandler, NULL);
702         AE_CHECK_OK (AcpiInstallNotifyHandler, Status);
703 
704         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
705                                             AeNotifyHandler);
706         AE_CHECK_OK (AcpiRemoveNotifyHandler, Status);
707 
708         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
709                                             AeNotifyHandler, NULL);
710         if (ACPI_FAILURE (Status))
711         {
712             printf ("Could not install a notify handler, %s\n",
713                 AcpiFormatException (Status));
714         }
715 
716         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
717         AE_CHECK_OK (AcpiAttachData, Status);
718 
719         Status = AcpiDetachData (Handle, AeAttachedDataHandler);
720         AE_CHECK_OK (AcpiDetachData, Status);
721 
722         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
723         AE_CHECK_OK (AcpiAttachData, Status);
724     }
725     else
726     {
727         printf ("No _SB_ found, %s\n", AcpiFormatException (Status));
728     }
729 
730 
731     /*
732      * Install handlers that will override the default handlers for some of
733      * the space IDs.
734      */
735     for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++)
736     {
737         /* Install handler at the root object */
738 
739         Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode,
740                     DefaultSpaceIdList[i], AeRegionHandler,
741                     AeRegionInit, NULL);
742         if (ACPI_FAILURE (Status))
743         {
744             ACPI_EXCEPTION ((AE_INFO, Status,
745                 "Could not install a default OpRegion handler for %s space(%u)",
746                 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]),
747                 DefaultSpaceIdList[i]));
748             return (Status);
749         }
750     }
751 
752     /*
753      * Initialize the global Region Handler space
754      * MCW 3/23/00
755      */
756     AeRegions.NumberOfRegions = 0;
757     AeRegions.RegionList = NULL;
758     return (Status);
759 }
760 
761 
762 /******************************************************************************
763  *
764  * FUNCTION:    AeRegionHandler
765  *
766  * PARAMETERS:  Standard region handler parameters
767  *
768  * RETURN:      Status
769  *
770  * DESCRIPTION: Test handler - Handles some dummy regions via memory that can
771  *              be manipulated in Ring 3. Simulates actual reads and writes.
772  *
773  *****************************************************************************/
774 
775 ACPI_STATUS
776 AeRegionHandler (
777     UINT32                  Function,
778     ACPI_PHYSICAL_ADDRESS   Address,
779     UINT32                  BitWidth,
780     UINT64                  *Value,
781     void                    *HandlerContext,
782     void                    *RegionContext)
783 {
784 
785     ACPI_OPERAND_OBJECT     *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
786     UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Value);
787     ACPI_PHYSICAL_ADDRESS   BaseAddress;
788     ACPI_SIZE               Length;
789     BOOLEAN                 BufferExists;
790     AE_REGION               *RegionElement;
791     void                    *BufferValue;
792     ACPI_STATUS             Status;
793     UINT32                  ByteWidth;
794     UINT32                  i;
795     UINT8                   SpaceId;
796 
797 
798     ACPI_FUNCTION_NAME (AeRegionHandler);
799 
800     /*
801      * If the object is not a region, simply return
802      */
803     if (RegionObject->Region.Type != ACPI_TYPE_REGION)
804     {
805         return (AE_OK);
806     }
807 
808     /*
809      * Region support can be disabled with the -r option.
810      * We use this to support dynamically loaded tables where we pass a valid
811      * address to the AML.
812      */
813     if (AcpiGbl_DbOpt_NoRegionSupport)
814     {
815         BufferValue = ACPI_TO_POINTER (Address);
816         ByteWidth = (BitWidth / 8);
817 
818         if (BitWidth % 8)
819         {
820             ByteWidth += 1;
821         }
822         goto DoFunction;
823     }
824 
825     /*
826      * Find the region's address space and length before searching
827      * the linked list.
828      */
829     BaseAddress = RegionObject->Region.Address;
830     Length = (ACPI_SIZE) RegionObject->Region.Length;
831     SpaceId = RegionObject->Region.SpaceId;
832 
833     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n",
834             AcpiUtGetRegionName (RegionObject->Region.SpaceId),
835             (UINT32) Address));
836 
837     switch (SpaceId)
838     {
839     case ACPI_ADR_SPACE_SYSTEM_IO:
840         /*
841          * For I/O space, exercise the port validation
842          */
843         switch (Function & ACPI_IO_MASK)
844         {
845         case ACPI_READ:
846             Status = AcpiHwReadPort (Address, (UINT32 *) Value, BitWidth);
847             AE_CHECK_OK (AcpiHwReadPort, Status);
848             break;
849 
850         case ACPI_WRITE:
851             Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth);
852             AE_CHECK_OK (AcpiHwWritePort, Status);
853             break;
854 
855         default:
856             Status = AE_BAD_PARAMETER;
857             break;
858         }
859 
860         if (ACPI_FAILURE (Status))
861         {
862             return (Status);
863         }
864 
865         /* Now go ahead and simulate the hardware */
866         break;
867 
868 
869     case ACPI_ADR_SPACE_SMBUS:
870 
871         Length = 0;
872 
873         switch (Function & ACPI_IO_MASK)
874         {
875         case ACPI_READ:
876             switch (Function >> 16)
877             {
878             case AML_FIELD_ATTRIB_SMB_QUICK:
879             case AML_FIELD_ATTRIB_SMB_SEND_RCV:
880             case AML_FIELD_ATTRIB_SMB_BYTE:
881                 Length = 1;
882                 break;
883 
884             case AML_FIELD_ATTRIB_SMB_WORD:
885             case AML_FIELD_ATTRIB_SMB_WORD_CALL:
886                 Length = 2;
887                 break;
888 
889             case AML_FIELD_ATTRIB_SMB_BLOCK:
890             case AML_FIELD_ATTRIB_SMB_BLOCK_CALL:
891                 Length = 32;
892                 break;
893 
894             default:
895                 break;
896             }
897             break;
898 
899         case ACPI_WRITE:
900             switch (Function >> 16)
901             {
902             case AML_FIELD_ATTRIB_SMB_QUICK:
903             case AML_FIELD_ATTRIB_SMB_SEND_RCV:
904             case AML_FIELD_ATTRIB_SMB_BYTE:
905             case AML_FIELD_ATTRIB_SMB_WORD:
906             case AML_FIELD_ATTRIB_SMB_BLOCK:
907                 Length = 0;
908                 break;
909 
910             case AML_FIELD_ATTRIB_SMB_WORD_CALL:
911                 Length = 2;
912                 break;
913 
914             case AML_FIELD_ATTRIB_SMB_BLOCK_CALL:
915                 Length = 32;
916                 break;
917 
918             default:
919                 break;
920             }
921             break;
922 
923         default:
924             break;
925         }
926 
927         for (i = 0; i < Length; i++)
928         {
929             Buffer[i+2] = (UINT8) (0xA0 + i);
930         }
931 
932         Buffer[0] = 0x7A;
933         Buffer[1] = (UINT8) Length;
934         return (AE_OK);
935 
936 
937     case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
938 
939         AcpiOsPrintf ("AcpiExec: Received IPMI request: "
940             "Address %X BaseAddress %X Length %X Width %X BufferLength %u\n",
941             (UINT32) Address, (UINT32) BaseAddress,
942             Length, BitWidth, Buffer[1]);
943 
944         /*
945          * Regardless of a READ or WRITE, this handler is passed a 66-byte
946          * buffer in which to return the IPMI status/length/data.
947          *
948          * Return some example data to show use of the bidirectional buffer
949          */
950         Buffer[0] = 0;       /* Status byte */
951         Buffer[1] = 64;      /* Return buffer data length */
952         Buffer[2] = 0;       /* Completion code */
953         Buffer[3] = 0x34;    /* Power measurement */
954         Buffer[4] = 0x12;    /* Power measurement */
955         Buffer[65] = 0xEE;   /* last buffer byte */
956         return (AE_OK);
957 
958     default:
959         break;
960     }
961 
962     /*
963      * Search through the linked list for this region's buffer
964      */
965     BufferExists = FALSE;
966     RegionElement = AeRegions.RegionList;
967 
968     if (AeRegions.NumberOfRegions)
969     {
970         while (!BufferExists && RegionElement)
971         {
972             if (RegionElement->Address == BaseAddress &&
973                 RegionElement->Length == Length &&
974                 RegionElement->SpaceId == SpaceId)
975             {
976                 BufferExists = TRUE;
977             }
978             else
979             {
980                 RegionElement = RegionElement->NextRegion;
981             }
982         }
983     }
984 
985     /*
986      * If the Region buffer does not exist, create it now
987      */
988     if (!BufferExists)
989     {
990         /*
991          * Do the memory allocations first
992          */
993         RegionElement = AcpiOsAllocate (sizeof (AE_REGION));
994         if (!RegionElement)
995         {
996             return (AE_NO_MEMORY);
997         }
998 
999         RegionElement->Buffer = AcpiOsAllocate (Length);
1000         if (!RegionElement->Buffer)
1001         {
1002             AcpiOsFree (RegionElement);
1003             return (AE_NO_MEMORY);
1004         }
1005 
1006         /* Initialize the region with the default fill value */
1007 
1008         ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length);
1009 
1010         RegionElement->Address      = BaseAddress;
1011         RegionElement->Length       = Length;
1012         RegionElement->SpaceId      = SpaceId;
1013         RegionElement->NextRegion   = NULL;
1014 
1015         /*
1016          * Increment the number of regions and put this one
1017          *  at the head of the list as it will probably get accessed
1018          *  more often anyway.
1019          */
1020         AeRegions.NumberOfRegions += 1;
1021 
1022         if (AeRegions.RegionList)
1023         {
1024             RegionElement->NextRegion = AeRegions.RegionList;
1025         }
1026 
1027         AeRegions.RegionList = RegionElement;
1028     }
1029 
1030     /*
1031      * Calculate the size of the memory copy
1032      */
1033     ByteWidth = (BitWidth / 8);
1034 
1035     if (BitWidth % 8)
1036     {
1037         ByteWidth += 1;
1038     }
1039 
1040     /*
1041      * The buffer exists and is pointed to by RegionElement.
1042      * We now need to verify the request is valid and perform the operation.
1043      *
1044      * NOTE: RegionElement->Length is in bytes, therefore it we compare against
1045      * ByteWidth (see above)
1046      */
1047     if (((UINT64) Address + ByteWidth) >
1048         ((UINT64)(RegionElement->Address) + RegionElement->Length))
1049     {
1050         ACPI_WARNING ((AE_INFO,
1051             "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X",
1052             (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address,
1053             ByteWidth, (UINT32)(RegionElement->Address),
1054             RegionElement->Length));
1055 
1056         return (AE_AML_REGION_LIMIT);
1057     }
1058 
1059     /*
1060      * Get BufferValue to point to the "address" in the buffer
1061      */
1062     BufferValue = ((UINT8 *) RegionElement->Buffer +
1063                     ((UINT64) Address - (UINT64) RegionElement->Address));
1064 
1065 DoFunction:
1066 
1067     /*
1068      * Perform a read or write to the buffer space
1069      */
1070     switch (Function)
1071     {
1072     case ACPI_READ:
1073         /*
1074          * Set the pointer Value to whatever is in the buffer
1075          */
1076         ACPI_MEMCPY (Value, BufferValue, ByteWidth);
1077         break;
1078 
1079     case ACPI_WRITE:
1080         /*
1081          * Write the contents of Value to the buffer
1082          */
1083         ACPI_MEMCPY (BufferValue, Value, ByteWidth);
1084         break;
1085 
1086     default:
1087         return (AE_BAD_PARAMETER);
1088     }
1089 
1090     return (AE_OK);
1091 }
1092 
1093 
1094