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