aehandlers.c revision 1.1.1.3 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