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