]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/acpica/lib-acpi/src/acpica/tools/acpiexec/aehandlers.c
Inital import
[l4.git] / l4 / pkg / acpica / lib-acpi / src / acpica / tools / acpiexec / aehandlers.c
1 /******************************************************************************
2  *
3  * Module Name: aehandlers - Various handlers for acpiexec
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights.  You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code.  No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision.  In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change.  Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee.  Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution.  In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government.  In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115
116 #include "aecommon.h"
117
118 #define _COMPONENT          ACPI_TOOLS
119         ACPI_MODULE_NAME    ("aehandlers")
120
121 /* Local prototypes */
122
123 void
124 AeNotifyHandler (
125     ACPI_HANDLE             Device,
126     UINT32                  Value,
127     void                    *Context);
128
129 void
130 AeDeviceNotifyHandler (
131     ACPI_HANDLE             Device,
132     UINT32                  Value,
133     void                    *Context);
134
135 ACPI_STATUS
136 AeExceptionHandler (
137     ACPI_STATUS             AmlStatus,
138     ACPI_NAME               Name,
139     UINT16                  Opcode,
140     UINT32                  AmlOffset,
141     void                    *Context);
142
143 ACPI_STATUS
144 AeTableHandler (
145     UINT32                  Event,
146     void                    *Table,
147     void                    *Context);
148
149 ACPI_STATUS
150 AeRegionInit (
151     ACPI_HANDLE             RegionHandle,
152     UINT32                  Function,
153     void                    *HandlerContext,
154     void                    **RegionContext);
155
156 void
157 AeAttachedDataHandler (
158     ACPI_HANDLE             Object,
159     void                    *Data);
160
161 UINT32                      SigintCount = 0;
162 AE_DEBUG_REGIONS            AeRegions;
163
164
165 /******************************************************************************
166  *
167  * FUNCTION:    AeCtrlCHandler
168  *
169  * PARAMETERS:  Sig
170  *
171  * RETURN:      none
172  *
173  * DESCRIPTION: Control-C handler.  Abort running control method if any.
174  *
175  *****************************************************************************/
176
177 void __cdecl
178 AeCtrlCHandler (
179     int                     Sig)
180 {
181
182     signal (SIGINT, SIG_IGN);
183     SigintCount++;
184
185     AcpiOsPrintf ("Caught a ctrl-c (#%d)\n\n", SigintCount);
186
187     if (AcpiGbl_MethodExecuting)
188     {
189         AcpiGbl_AbortMethod = TRUE;
190         signal (SIGINT, AeCtrlCHandler);
191
192         if (SigintCount < 10)
193         {
194             return;
195         }
196     }
197
198     exit (0);
199 }
200
201
202 /******************************************************************************
203  *
204  * FUNCTION:    AeNotifyHandler
205  *
206  * PARAMETERS:  Standard notify handler parameters
207  *
208  * RETURN:      Status
209  *
210  * DESCRIPTION: System notify handler for AcpiExec utility.  Used by the ASL
211  *              test suite(s) to communicate errors and other information to
212  *              this utility via the Notify() operator.
213  *
214  *****************************************************************************/
215
216 void
217 AeNotifyHandler (
218     ACPI_HANDLE                 Device,
219     UINT32                      Value,
220     void                        *Context)
221 {
222
223     switch (Value)
224     {
225 #if 0
226     case 0:
227         printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value);
228         if (AcpiGbl_DebugFile)
229         {
230             AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n");
231         }
232         break;
233
234
235     case 1:
236         printf ("[AcpiExec] Method Error: Incorrect numeric result\n");
237         if (AcpiGbl_DebugFile)
238         {
239             AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n");
240         }
241         break;
242
243
244     case 2:
245         printf ("[AcpiExec] Method Error: An operand was overwritten\n");
246         if (AcpiGbl_DebugFile)
247         {
248             AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n");
249         }
250         break;
251
252 #endif
253
254     default:
255         printf ("[AcpiExec] Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
256             AcpiUtGetNodeName (Device), Device, Value,
257             AcpiUtGetNotifyName (Value));
258         if (AcpiGbl_DebugFile)
259         {
260             AcpiOsPrintf ("[AcpiExec] Received a system notify, Value 0x%2.2X\n", Value);
261         }
262
263         (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
264         break;
265     }
266
267 }
268
269
270 /******************************************************************************
271  *
272  * FUNCTION:    AeDeviceNotifyHandler
273  *
274  * PARAMETERS:  Standard notify handler parameters
275  *
276  * RETURN:      Status
277  *
278  * DESCRIPTION: Device notify handler for AcpiExec utility.  Used by the ASL
279  *              test suite(s) to communicate errors and other information to
280  *              this utility via the Notify() operator.
281  *
282  *****************************************************************************/
283
284 void
285 AeDeviceNotifyHandler (
286     ACPI_HANDLE                 Device,
287     UINT32                      Value,
288     void                        *Context)
289 {
290
291     printf ("[AcpiExec] Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
292         AcpiUtGetNodeName (Device), Device, Value,
293         AcpiUtGetNotifyName (Value));
294     if (AcpiGbl_DebugFile)
295     {
296         AcpiOsPrintf ("[AcpiExec] Received a device notify, Value 0x%2.2X\n", Value);
297     }
298
299     (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
300 }
301
302
303 /******************************************************************************
304  *
305  * FUNCTION:    AeExceptionHandler
306  *
307  * PARAMETERS:  Standard exception handler parameters
308  *
309  * RETURN:      Status
310  *
311  * DESCRIPTION: System exception handler for AcpiExec utility.
312  *
313  *****************************************************************************/
314
315 ACPI_STATUS
316 AeExceptionHandler (
317     ACPI_STATUS             AmlStatus,
318     ACPI_NAME               Name,
319     UINT16                  Opcode,
320     UINT32                  AmlOffset,
321     void                    *Context)
322 {
323     ACPI_STATUS             NewAmlStatus = AmlStatus;
324     ACPI_STATUS             Status;
325     ACPI_BUFFER             ReturnObj;
326     ACPI_OBJECT_LIST        ArgList;
327     ACPI_OBJECT             Arg[3];
328     const char              *Exception;
329
330
331     Exception = AcpiFormatException (AmlStatus);
332     AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception);
333     if (Name)
334     {
335         AcpiOsPrintf ("of method [%4.4s]", (char *) &Name);
336     }
337     else
338     {
339         AcpiOsPrintf ("at module level (table load)");
340     }
341     AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset);
342
343     /*
344      * Invoke the _ERR method if present
345      *
346      * Setup parameter object
347      */
348     ArgList.Count = 3;
349     ArgList.Pointer = Arg;
350
351     Arg[0].Type = ACPI_TYPE_INTEGER;
352     Arg[0].Integer.Value = AmlStatus;
353
354     Arg[1].Type = ACPI_TYPE_STRING;
355     Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
356     Arg[1].String.Length = ACPI_STRLEN (Exception);
357
358     Arg[2].Type = ACPI_TYPE_INTEGER;
359     Arg[2].Integer.Value = ACPI_TO_INTEGER (AcpiOsGetThreadId());
360
361     /* Setup return buffer */
362
363     ReturnObj.Pointer = NULL;
364     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
365
366     Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj);
367     if (ACPI_SUCCESS (Status))
368     {
369         if (ReturnObj.Pointer)
370         {
371             /* Override original status */
372
373             NewAmlStatus = (ACPI_STATUS)
374                 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
375
376             AcpiOsFree (ReturnObj.Pointer);
377         }
378     }
379     else if (Status != AE_NOT_FOUND)
380     {
381         AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n",
382             AcpiFormatException (Status));
383     }
384
385     /* Global override */
386
387     if (AcpiGbl_IgnoreErrors)
388     {
389         NewAmlStatus = AE_OK;
390     }
391
392     if (NewAmlStatus != AmlStatus)
393     {
394         AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n",
395             AcpiFormatException (NewAmlStatus));
396     }
397
398     return (NewAmlStatus);
399 }
400
401
402 /******************************************************************************
403  *
404  * FUNCTION:    AeTableHandler
405  *
406  * PARAMETERS:  Table handler
407  *
408  * RETURN:      Status
409  *
410  * DESCRIPTION: System table handler for AcpiExec utility.
411  *
412  *****************************************************************************/
413
414 char                *TableEvents[] =
415 {
416     "LOAD",
417     "UNLOAD",
418     "UNKNOWN"
419 };
420
421 ACPI_STATUS
422 AeTableHandler (
423     UINT32                  Event,
424     void                    *Table,
425     void                    *Context)
426 {
427
428     if (Event > ACPI_NUM_TABLE_EVENTS)
429     {
430         Event = ACPI_NUM_TABLE_EVENTS;
431     }
432
433     /* TBD: could dump entire table header, need a header dump routine */
434
435     printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n",
436         TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table);
437     return (AE_OK);
438 }
439
440
441 /******************************************************************************
442  *
443  * FUNCTION:    AeGpeHandler
444  *
445  * DESCRIPTION: GPE handler for acpiexec
446  *
447  *****************************************************************************/
448
449 UINT32
450 AeGpeHandler (
451     void                    *Context)
452 {
453     AcpiOsPrintf ("Received a GPE at handler\n");
454     return (0);
455 }
456
457
458 /******************************************************************************
459  *
460  * FUNCTION:    AeAttachedDataHandler
461  *
462  * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
463  *              AcpiAttachData)
464  *
465  *****************************************************************************/
466
467 void
468 AeAttachedDataHandler (
469     ACPI_HANDLE             Object,
470     void                    *Data)
471 {
472     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
473
474
475     AcpiOsPrintf ("Received an attached data deletion on %4.4s\n",
476         Node->Name.Ascii);
477 }
478
479
480 /******************************************************************************
481  *
482  * FUNCTION:    AeRegionInit
483  *
484  * PARAMETERS:  None
485  *
486  * RETURN:      Status
487  *
488  * DESCRIPTION: Opregion init function.
489  *
490  *****************************************************************************/
491
492 ACPI_STATUS
493 AeRegionInit (
494     ACPI_HANDLE                 RegionHandle,
495     UINT32                      Function,
496     void                        *HandlerContext,
497     void                        **RegionContext)
498 {
499     /*
500      * Real simple, set the RegionContext to the RegionHandle
501      */
502     *RegionContext = RegionHandle;
503
504     return AE_OK;
505 }
506
507
508 /******************************************************************************
509  *
510  * FUNCTION:    AeInstallHandlers
511  *
512  * PARAMETERS:  None
513  *
514  * RETURN:      Status
515  *
516  * DESCRIPTION: Install handlers for the AcpiExec utility.
517  *
518  *****************************************************************************/
519
520 ACPI_ADR_SPACE_TYPE         SpaceId[] = {0, 1, 2, 3, 4, 5, 6, 7, 0x80};
521 #define AEXEC_NUM_REGIONS   9
522
523 ACPI_STATUS
524 AeInstallHandlers (void)
525 {
526     ACPI_STATUS             Status;
527     UINT32                  i;
528     ACPI_HANDLE             Handle;
529
530
531     ACPI_FUNCTION_ENTRY ();
532
533
534     Status = AcpiInstallTableHandler (AeTableHandler, NULL);
535     if (ACPI_FAILURE (Status))
536     {
537         printf ("Could not install table handler, %s\n",
538             AcpiFormatException (Status));
539     }
540
541     Status = AcpiInstallExceptionHandler (AeExceptionHandler);
542     if (ACPI_FAILURE (Status))
543     {
544         printf ("Could not install exception handler, %s\n",
545             AcpiFormatException (Status));
546     }
547
548     /* Install global notify handler */
549
550     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
551                                         AeNotifyHandler, NULL);
552     if (ACPI_FAILURE (Status))
553     {
554         printf ("Could not install a global notify handler, %s\n",
555             AcpiFormatException (Status));
556     }
557
558     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
559                                         AeDeviceNotifyHandler, NULL);
560     if (ACPI_FAILURE (Status))
561     {
562         printf ("Could not install a global notify handler, %s\n",
563             AcpiFormatException (Status));
564     }
565
566     Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
567     if (ACPI_SUCCESS (Status))
568     {
569         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
570                                             AeNotifyHandler, NULL);
571         if (ACPI_FAILURE (Status))
572         {
573             printf ("Could not install a notify handler, %s\n",
574                 AcpiFormatException (Status));
575         }
576
577         Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
578                                             AeNotifyHandler);
579         if (ACPI_FAILURE (Status))
580         {
581             printf ("Could not remove a notify handler, %s\n",
582                 AcpiFormatException (Status));
583         }
584
585         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
586                                             AeNotifyHandler, NULL);
587         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
588                                             AeNotifyHandler);
589         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
590                                             AeNotifyHandler, NULL);
591         if (ACPI_FAILURE (Status))
592         {
593             printf ("Could not install a notify handler, %s\n",
594                 AcpiFormatException (Status));
595         }
596
597         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
598         Status = AcpiDetachData (Handle, AeAttachedDataHandler);
599         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
600     }
601     else
602     {
603         printf ("No _SB_ found, %s\n", AcpiFormatException (Status));
604     }
605
606     /* Set a handler for all supported operation regions */
607
608     for (i = 0; i < AEXEC_NUM_REGIONS; i++)
609     {
610         Status = AcpiRemoveAddressSpaceHandler (AcpiGbl_RootNode,
611                         SpaceId[i], AeRegionHandler);
612
613         /* Install handler at the root object.
614          * TBD: all default handlers should be installed here!
615          */
616         Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode,
617                         SpaceId[i], AeRegionHandler, AeRegionInit, NULL);
618         if (ACPI_FAILURE (Status))
619         {
620             ACPI_EXCEPTION ((AE_INFO, Status,
621                 "Could not install an OpRegion handler for %s space(%d)",
622                 AcpiUtGetRegionName((UINT8) SpaceId[i]), SpaceId[i]));
623             return (Status);
624         }
625     }
626
627     /*
628      * Initialize the global Region Handler space
629      * MCW 3/23/00
630      */
631     AeRegions.NumberOfRegions = 0;
632     AeRegions.RegionList = NULL;
633
634     return Status;
635 }
636
637
638 /******************************************************************************
639  *
640  * FUNCTION:    AeRegionHandler
641  *
642  * PARAMETERS:  Standard region handler parameters
643  *
644  * RETURN:      Status
645  *
646  * DESCRIPTION: Test handler - Handles some dummy regions via memory that can
647  *              be manipulated in Ring 3. Simulates actual reads and writes.
648  *
649  *****************************************************************************/
650
651 ACPI_STATUS
652 AeRegionHandler (
653     UINT32                  Function,
654     ACPI_PHYSICAL_ADDRESS   Address,
655     UINT32                  BitWidth,
656     ACPI_INTEGER            *Value,
657     void                    *HandlerContext,
658     void                    *RegionContext)
659 {
660
661     ACPI_OPERAND_OBJECT     *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
662     UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Value);
663     ACPI_PHYSICAL_ADDRESS   BaseAddress;
664     ACPI_SIZE               Length;
665     BOOLEAN                 BufferExists;
666     AE_REGION               *RegionElement;
667     void                    *BufferValue;
668     ACPI_STATUS             Status;
669     UINT32                  ByteWidth;
670     UINT32                  i;
671     UINT8                   SpaceId;
672
673
674     ACPI_FUNCTION_NAME (AeRegionHandler);
675
676     /*
677      * If the object is not a region, simply return
678      */
679     if (RegionObject->Region.Type != ACPI_TYPE_REGION)
680     {
681         return AE_OK;
682     }
683
684     /*
685      * Region support can be disabled with the -r option.
686      * We use this to support dynamically loaded tables where we pass a valid
687      * address to the AML.
688      */
689     if (AcpiGbl_DbOpt_NoRegionSupport)
690     {
691         BufferValue = ACPI_TO_POINTER (Address);
692         ByteWidth = (BitWidth / 8);
693
694         if (BitWidth % 8)
695         {
696             ByteWidth += 1;
697         }
698         goto DoFunction;
699     }
700
701     /*
702      * Find the region's address space and length before searching
703      * the linked list.
704      */
705     BaseAddress = RegionObject->Region.Address;
706     Length = (ACPI_SIZE) RegionObject->Region.Length;
707     SpaceId = RegionObject->Region.SpaceId;
708
709     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n",
710             AcpiUtGetRegionName (RegionObject->Region.SpaceId),
711             (UINT32) Address));
712
713     switch (SpaceId)
714     {
715     case ACPI_ADR_SPACE_SYSTEM_IO:
716         /*
717          * For I/O space, exercise the port validation
718          */
719         switch (Function & ACPI_IO_MASK)
720         {
721         case ACPI_READ:
722             Status = AcpiHwReadPort (Address, (UINT32 *) Value, BitWidth);
723             break;
724
725         case ACPI_WRITE:
726             Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth);
727             break;
728
729         default:
730             Status = AE_BAD_PARAMETER;
731             break;
732         }
733
734         if (ACPI_FAILURE (Status))
735         {
736             return (Status);
737         }
738
739         /* Now go ahead and simulate the hardware */
740         break;
741
742
743     case ACPI_ADR_SPACE_SMBUS:
744
745         Length = 0;
746
747         switch (Function & ACPI_IO_MASK)
748         {
749         case ACPI_READ:
750             switch (Function >> 16)
751             {
752             case AML_FIELD_ATTRIB_SMB_QUICK:
753             case AML_FIELD_ATTRIB_SMB_SEND_RCV:
754             case AML_FIELD_ATTRIB_SMB_BYTE:
755                 Length = 1;
756                 break;
757
758             case AML_FIELD_ATTRIB_SMB_WORD:
759             case AML_FIELD_ATTRIB_SMB_WORD_CALL:
760                 Length = 2;
761                 break;
762
763             case AML_FIELD_ATTRIB_SMB_BLOCK:
764             case AML_FIELD_ATTRIB_SMB_BLOCK_CALL:
765                 Length = 32;
766                 break;
767
768             default:
769                 break;
770             }
771             break;
772
773         case ACPI_WRITE:
774             switch (Function >> 16)
775             {
776             case AML_FIELD_ATTRIB_SMB_QUICK:
777             case AML_FIELD_ATTRIB_SMB_SEND_RCV:
778             case AML_FIELD_ATTRIB_SMB_BYTE:
779             case AML_FIELD_ATTRIB_SMB_WORD:
780             case AML_FIELD_ATTRIB_SMB_BLOCK:
781                 Length = 0;
782                 break;
783
784             case AML_FIELD_ATTRIB_SMB_WORD_CALL:
785                 Length = 2;
786                 break;
787
788             case AML_FIELD_ATTRIB_SMB_BLOCK_CALL:
789                 Length = 32;
790                 break;
791
792             default:
793                 break;
794             }
795             break;
796
797         default:
798             break;
799         }
800
801         for (i = 0; i < Length; i++)
802         {
803             Buffer[i+2] = (UINT8) (0xA0 + i);
804         }
805
806         Buffer[0] = 0x7A;
807         Buffer[1] = (UINT8) Length;
808         return (AE_OK);
809
810
811     case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
812
813         AcpiOsPrintf ("AcpiExec: Received IPMI request: "
814             "Address %X BaseAddress %X Length %X Width %X BufferLength %u\n",
815             (UINT32) Address, (UINT32) BaseAddress,
816             Length, BitWidth, Buffer[1]);
817
818         /*
819          * Regardless of a READ or WRITE, this handler is passed a 66-byte
820          * buffer in which to return the IPMI status/length/data.
821          *
822          * Return some example data to show use of the bidirectional buffer
823          */
824         Buffer[0] = 0;       /* Status byte */
825         Buffer[1] = 64;      /* Return buffer data length */
826         Buffer[2] = 0;       /* Completion code */
827         Buffer[3] = 0x34;    /* Power measurement */
828         Buffer[4] = 0x12;    /* Power measurement */
829         Buffer[65] = 0xEE;   /* last buffer byte */
830         return (AE_OK);
831
832     default:
833         break;
834     }
835
836     /*
837      * Search through the linked list for this region's buffer
838      */
839     BufferExists = FALSE;
840     RegionElement = AeRegions.RegionList;
841
842     if (AeRegions.NumberOfRegions)
843     {
844         while (!BufferExists && RegionElement)
845         {
846             if (RegionElement->Address == BaseAddress &&
847                 RegionElement->Length == Length &&
848                 RegionElement->SpaceId == SpaceId)
849             {
850                 BufferExists = TRUE;
851             }
852             else
853             {
854                 RegionElement = RegionElement->NextRegion;
855             }
856         }
857     }
858
859     /*
860      * If the Region buffer does not exist, create it now
861      */
862     if (!BufferExists)
863     {
864         /*
865          * Do the memory allocations first
866          */
867         RegionElement = AcpiOsAllocate (sizeof (AE_REGION));
868         if (!RegionElement)
869         {
870             return AE_NO_MEMORY;
871         }
872
873         RegionElement->Buffer = AcpiOsAllocate (Length);
874         if (!RegionElement->Buffer)
875         {
876             AcpiOsFree (RegionElement);
877             return AE_NO_MEMORY;
878         }
879
880         /* Initialize the region with the default fill value */
881
882         ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length);
883
884         RegionElement->Address      = BaseAddress;
885         RegionElement->Length       = Length;
886         RegionElement->SpaceId      = SpaceId;
887         RegionElement->NextRegion   = NULL;
888
889         /*
890          * Increment the number of regions and put this one
891          *  at the head of the list as it will probably get accessed
892          *  more often anyway.
893          */
894         AeRegions.NumberOfRegions += 1;
895
896         if (AeRegions.RegionList)
897         {
898             RegionElement->NextRegion = AeRegions.RegionList;
899         }
900
901         AeRegions.RegionList = RegionElement;
902     }
903
904     /*
905      * Calculate the size of the memory copy
906      */
907     ByteWidth = (BitWidth / 8);
908
909     if (BitWidth % 8)
910     {
911         ByteWidth += 1;
912     }
913
914     /*
915      * The buffer exists and is pointed to by RegionElement.
916      * We now need to verify the request is valid and perform the operation.
917      *
918      * NOTE: RegionElement->Length is in bytes, therefore it we compare against
919      * ByteWidth (see above)
920      */
921     if (((ACPI_INTEGER) Address + ByteWidth) >
922         ((ACPI_INTEGER)(RegionElement->Address) + RegionElement->Length))
923     {
924         ACPI_WARNING ((AE_INFO,
925             "Request on [%4.4s] is beyond region limit Req-%X+%X, Base=%X, Len-%X",
926             (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address,
927             ByteWidth, (UINT32)(RegionElement->Address),
928             RegionElement->Length));
929
930         return AE_AML_REGION_LIMIT;
931     }
932
933     /*
934      * Get BufferValue to point to the "address" in the buffer
935      */
936     BufferValue = ((UINT8 *) RegionElement->Buffer +
937                     ((ACPI_INTEGER) Address - (ACPI_INTEGER) RegionElement->Address));
938
939 DoFunction:
940
941     /*
942      * Perform a read or write to the buffer space
943      */
944     switch (Function)
945     {
946     case ACPI_READ:
947         /*
948          * Set the pointer Value to whatever is in the buffer
949          */
950         ACPI_MEMCPY (Value, BufferValue, ByteWidth);
951         break;
952
953     case ACPI_WRITE:
954         /*
955          * Write the contents of Value to the buffer
956          */
957         ACPI_MEMCPY (BufferValue, Value, ByteWidth);
958         break;
959
960     default:
961         return AE_BAD_PARAMETER;
962     }
963     return AE_OK;
964 }
965
966