1 /******************************************************************************
3 * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
6 *****************************************************************************/
8 /******************************************************************************
12 * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
13 * All rights reserved.
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights. You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code. No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
38 * The above copyright and patent license is granted only if the following
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision. In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change. Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee. Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution. In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
73 * 3.4. Intel retains all right, title, and interest in and to the Original
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
81 * 4. Disclaimer and Export Compliance
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government. In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
115 *****************************************************************************/
116 /* $DragonFly: src/sys/contrib/dev/acpica/Attic/evregion.c,v 1.1 2003/09/24 03:32:15 drhodus Exp $ */
119 #define __EVREGION_C__
122 #include "acevents.h"
123 #include "acnamesp.h"
124 #include "acinterp.h"
126 #define _COMPONENT ACPI_EVENTS
127 ACPI_MODULE_NAME ("evregion")
130 /*******************************************************************************
132 * FUNCTION: AcpiEvInitAddressSpaces
138 * DESCRIPTION: Installs the core subsystem address space handlers.
140 ******************************************************************************/
143 AcpiEvInitAddressSpaces (
149 ACPI_FUNCTION_TRACE ("EvInitAddressSpaces");
153 * All address spaces (PCI Config, EC, SMBus) are scope dependent
154 * and registration must occur for a specific device. In the case
155 * system memory and IO address spaces there is currently no device
156 * associated with the address space. For these we use the root.
157 * We install the default PCI config space handler at the root so
158 * that this space is immediately available even though the we have
159 * not enumerated all the PCI Root Buses yet. This is to conform
160 * to the ACPI specification which states that the PCI config
161 * space must be always available -- even though we are nowhere
162 * near ready to find the PCI root buses at this point.
164 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
165 * has already been installed (via AcpiInstallAddressSpaceHandler)
168 Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
169 ACPI_ADR_SPACE_SYSTEM_MEMORY,
170 ACPI_DEFAULT_HANDLER, NULL, NULL);
171 if ((ACPI_FAILURE (Status)) &&
172 (Status != AE_ALREADY_EXISTS))
174 return_ACPI_STATUS (Status);
177 Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
178 ACPI_ADR_SPACE_SYSTEM_IO,
179 ACPI_DEFAULT_HANDLER, NULL, NULL);
180 if ((ACPI_FAILURE (Status)) &&
181 (Status != AE_ALREADY_EXISTS))
183 return_ACPI_STATUS (Status);
186 Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
187 ACPI_ADR_SPACE_PCI_CONFIG,
188 ACPI_DEFAULT_HANDLER, NULL, NULL);
189 if ((ACPI_FAILURE (Status)) &&
190 (Status != AE_ALREADY_EXISTS))
192 return_ACPI_STATUS (Status);
195 Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
196 ACPI_ADR_SPACE_DATA_TABLE,
197 ACPI_DEFAULT_HANDLER, NULL, NULL);
198 if ((ACPI_FAILURE (Status)) &&
199 (Status != AE_ALREADY_EXISTS))
201 return_ACPI_STATUS (Status);
204 return_ACPI_STATUS (AE_OK);
208 /*******************************************************************************
210 * FUNCTION: AcpiEvExecuteRegMethod
212 * PARAMETERS: RegionObj - Object structure
213 * Function - On (1) or Off (0)
217 * DESCRIPTION: Execute _REG method for a region
219 ******************************************************************************/
222 AcpiEvExecuteRegMethod (
223 ACPI_OPERAND_OBJECT *RegionObj,
226 ACPI_OPERAND_OBJECT *Params[3];
227 ACPI_OPERAND_OBJECT *RegionObj2;
231 ACPI_FUNCTION_TRACE ("EvExecuteRegMethod");
234 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
237 return_ACPI_STATUS (AE_NOT_EXIST);
240 if (RegionObj2->Extra.Method_REG == NULL)
242 return_ACPI_STATUS (AE_OK);
246 * _REG method has two arguments
247 * Arg0: Integer: Operation region space ID
248 * Same value as RegionObj->Region.SpaceId
249 * Arg1: Integer: connection status
250 * 1 for connecting the handler,
251 * 0 for disconnecting the handler
252 * Passed as a parameter
254 Params[0] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
257 return_ACPI_STATUS (AE_NO_MEMORY);
260 Params[1] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
263 Status = AE_NO_MEMORY;
268 * Set up the parameter objects
270 Params[0]->Integer.Value = RegionObj->Region.SpaceId;
271 Params[1]->Integer.Value = Function;
275 * Execute the method, no return value
277 ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, RegionObj2->Extra.Method_REG, NULL));
278 Status = AcpiNsEvaluateByHandle (RegionObj2->Extra.Method_REG, Params, NULL);
280 AcpiUtRemoveReference (Params[1]);
283 AcpiUtRemoveReference (Params[0]);
285 return_ACPI_STATUS (Status);
289 /*******************************************************************************
291 * FUNCTION: AcpiEvAddressSpaceDispatch
293 * PARAMETERS: RegionObj - internal region object
294 * SpaceId - ID of the address space (0-255)
295 * Function - Read or Write operation
296 * Address - Where in the space to read or write
297 * BitWidth - Field width in bits (8, 16, 32, or 64)
298 * Value - Pointer to in or out value
302 * DESCRIPTION: Dispatch an address space or operation region access to
303 * a previously installed handler.
305 ******************************************************************************/
308 AcpiEvAddressSpaceDispatch (
309 ACPI_OPERAND_OBJECT *RegionObj,
311 ACPI_PHYSICAL_ADDRESS Address,
317 ACPI_ADR_SPACE_HANDLER Handler;
318 ACPI_ADR_SPACE_SETUP RegionSetup;
319 ACPI_OPERAND_OBJECT *HandlerDesc;
320 ACPI_OPERAND_OBJECT *RegionObj2;
321 void *RegionContext = NULL;
324 ACPI_FUNCTION_TRACE ("EvAddressSpaceDispatch");
327 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
330 return_ACPI_STATUS (AE_NOT_EXIST);
334 * Ensure that there is a handler associated with this region
336 HandlerDesc = RegionObj->Region.AddrHandler;
339 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n",
340 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
342 return_ACPI_STATUS (AE_NOT_EXIST);
346 * It may be the case that the region has never been initialized
347 * Some types of regions require special init code
349 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
352 * This region has not been initialized yet, do it
354 RegionSetup = HandlerDesc->AddrHandler.Setup;
358 * Bad news, no init routine and not init'd
360 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
361 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
362 return_ACPI_STATUS (AE_UNKNOWN_STATUS);
366 * We must exit the interpreter because the region setup will potentially
367 * execute control methods
369 AcpiExExitInterpreter ();
371 Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
372 HandlerDesc->AddrHandler.Context, &RegionContext);
374 /* Re-enter the interpreter */
376 Status2 = AcpiExEnterInterpreter ();
377 if (ACPI_FAILURE (Status2))
379 return_ACPI_STATUS (Status2);
383 * Init routine may fail
385 if (ACPI_FAILURE (Status))
387 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
388 AcpiFormatException (Status),
389 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
390 return_ACPI_STATUS (Status);
393 RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
396 * Save the returned context for use in all accesses to
397 * this particular region.
399 RegionObj2->Extra.RegionContext = RegionContext;
403 * We have everything we need, begin the process
405 Handler = HandlerDesc->AddrHandler.Handler;
407 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
408 "Addrhandler %p (%p), Address %8.8X%8.8X\n",
409 &RegionObj->Region.AddrHandler->AddrHandler, Handler,
410 ACPI_HIDWORD (Address), ACPI_LODWORD (Address)));
412 if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
415 * For handlers other than the default (supplied) handlers, we must
416 * exit the interpreter because the handler *might* block -- we don't
417 * know what it will do, so we can't hold the lock on the intepreter.
419 AcpiExExitInterpreter();
423 * Invoke the handler.
425 Status = Handler (Function, Address, BitWidth, Value,
426 HandlerDesc->AddrHandler.Context,
427 RegionObj2->Extra.RegionContext);
429 if (ACPI_FAILURE (Status))
431 ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
432 AcpiUtGetRegionName (RegionObj->Region.SpaceId),
433 AcpiFormatException (Status)));
436 if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
439 * We just returned from a non-default handler, we must re-enter the
442 Status2 = AcpiExEnterInterpreter ();
443 if (ACPI_FAILURE (Status2))
445 return_ACPI_STATUS (Status2);
449 return_ACPI_STATUS (Status);
452 /*******************************************************************************
454 * FUNCTION: AcpiEvDetachRegion
456 * PARAMETERS: RegionObj - Region Object
457 * AcpiNsIsLocked - Namespace Region Already Locked?
461 * DESCRIPTION: Break the association between the handler and the region
462 * this is a two way association.
464 ******************************************************************************/
468 ACPI_OPERAND_OBJECT *RegionObj,
469 BOOLEAN AcpiNsIsLocked)
471 ACPI_OPERAND_OBJECT *HandlerObj;
472 ACPI_OPERAND_OBJECT *ObjDesc;
473 ACPI_OPERAND_OBJECT **LastObjPtr;
474 ACPI_ADR_SPACE_SETUP RegionSetup;
476 ACPI_OPERAND_OBJECT *RegionObj2;
480 ACPI_FUNCTION_TRACE ("EvDetachRegion");
483 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
488 RegionContext = RegionObj2->Extra.RegionContext;
491 * Get the address handler from the region object
493 HandlerObj = RegionObj->Region.AddrHandler;
497 * This region has no handler, all done
504 * Find this region in the handler's list
506 ObjDesc = HandlerObj->AddrHandler.RegionList;
507 LastObjPtr = &HandlerObj->AddrHandler.RegionList;
512 * See if this is the one
514 if (ObjDesc == RegionObj)
516 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
517 "Removing Region %p from address handler %p\n",
518 RegionObj, HandlerObj));
520 * This is it, remove it from the handler's list
522 *LastObjPtr = ObjDesc->Region.Next;
523 ObjDesc->Region.Next = NULL; /* Must clear field */
527 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
528 if (ACPI_FAILURE (Status))
535 * Now stop region accesses by executing the _REG method
537 Status = AcpiEvExecuteRegMethod (RegionObj, 0);
538 if (ACPI_FAILURE (Status))
540 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
541 AcpiFormatException (Status),
542 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
547 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
548 if (ACPI_FAILURE (Status))
555 * Call the setup handler with the deactivate notification
557 RegionSetup = HandlerObj->AddrHandler.Setup;
558 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
559 HandlerObj->AddrHandler.Context, &RegionContext);
562 * Init routine may fail, Just ignore errors
564 if (ACPI_FAILURE (Status))
566 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
567 AcpiFormatException (Status),
568 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
571 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
574 * Remove handler reference in the region
576 * NOTE: this doesn't mean that the region goes away
577 * The region is just inaccessible as indicated to
580 * If the region is on the handler's list
581 * this better be the region's handler
583 RegionObj->Region.AddrHandler = NULL;
587 } /* found the right handler */
590 * Move through the linked list of handlers
592 LastObjPtr = &ObjDesc->Region.Next;
593 ObjDesc = ObjDesc->Region.Next;
597 * If we get here, the region was not in the handler's region list
599 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
600 "Cannot remove region %p from address handler %p\n",
601 RegionObj, HandlerObj));
607 /*******************************************************************************
609 * FUNCTION: AcpiEvAttachRegion
611 * PARAMETERS: HandlerObj - Handler Object
612 * RegionObj - Region Object
613 * AcpiNsIsLocked - Namespace Region Already Locked?
617 * DESCRIPTION: Create the association between the handler and the region
618 * this is a two way association.
620 ******************************************************************************/
624 ACPI_OPERAND_OBJECT *HandlerObj,
625 ACPI_OPERAND_OBJECT *RegionObj,
626 BOOLEAN AcpiNsIsLocked)
632 ACPI_FUNCTION_TRACE ("EvAttachRegion");
635 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
636 "Adding Region %p to address handler %p [%s]\n",
637 RegionObj, HandlerObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
641 * Link this region to the front of the handler's list
643 RegionObj->Region.Next = HandlerObj->AddrHandler.RegionList;
644 HandlerObj->AddrHandler.RegionList = RegionObj;
647 * Set the region's handler
649 RegionObj->Region.AddrHandler = HandlerObj;
652 * Tell all users that this region is usable by running the _REG
657 Status2 = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
658 if (ACPI_FAILURE (Status2))
660 return_ACPI_STATUS (Status2);
664 Status = AcpiEvExecuteRegMethod (RegionObj, 1);
668 Status2 = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
669 if (ACPI_FAILURE (Status2))
671 return_ACPI_STATUS (Status2);
675 return_ACPI_STATUS (Status);
679 /*******************************************************************************
681 * FUNCTION: AcpiEvAddrHandlerHelper
683 * PARAMETERS: Handle - Node to be dumped
684 * Level - Nesting level of the handle
685 * Context - Passed into AcpiNsWalkNamespace
687 * DESCRIPTION: This routine installs an address handler into objects that are
690 * If the Object is a Device, and the device has a handler of
691 * the same type then the search is terminated in that branch.
693 * This is because the existing handler is closer in proximity
694 * to any more regions than the one we are trying to install.
696 ******************************************************************************/
699 AcpiEvAddrHandlerHelper (
700 ACPI_HANDLE ObjHandle,
705 ACPI_OPERAND_OBJECT *HandlerObj;
706 ACPI_OPERAND_OBJECT *TmpObj;
707 ACPI_OPERAND_OBJECT *ObjDesc;
708 ACPI_NAMESPACE_NODE *Node;
712 ACPI_FUNCTION_NAME ("EvAddrHandlerHelper");
715 HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
717 /* Parameter validation */
724 /* Convert and validate the device handle */
726 Node = AcpiNsMapHandleToNode (ObjHandle);
729 return (AE_BAD_PARAMETER);
733 * We only care about regions.and objects
734 * that can have address handlers
736 if ((Node->Type != ACPI_TYPE_DEVICE) &&
737 (Node->Type != ACPI_TYPE_REGION) &&
738 (Node != AcpiGbl_RootNode))
743 /* Check for an existing internal object */
745 ObjDesc = AcpiNsGetAttachedObject (Node);
749 * The object DNE, we don't care about it
755 * Devices are handled different than regions
757 if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_DEVICE)
760 * See if this guy has any handlers
762 TmpObj = ObjDesc->Device.AddrHandler;
766 * Now let's see if it's for the same address space.
768 if (TmpObj->AddrHandler.SpaceId == HandlerObj->AddrHandler.SpaceId)
771 * It's for the same address space
773 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
774 "Found handler for region [%s] in device %p(%p) handler %p\n",
775 AcpiUtGetRegionName (HandlerObj->AddrHandler.SpaceId),
776 ObjDesc, TmpObj, HandlerObj));
779 * Since the object we found it on was a device, then it
780 * means that someone has already installed a handler for
781 * the branch of the namespace from this device on. Just
782 * bail out telling the walk routine to not traverse this
783 * branch. This preserves the scoping rule for handlers.
785 return (AE_CTRL_DEPTH);
789 * Move through the linked list of handlers
791 TmpObj = TmpObj->AddrHandler.Next;
795 * As long as the device didn't have a handler for this
796 * space we don't care about it. We just ignore it and
803 * Only here if it was a region
805 if (ObjDesc->Region.SpaceId != HandlerObj->AddrHandler.SpaceId)
808 * This region is for a different address space
815 * Now we have a region and it is for the handler's address
818 * First disconnect region for any previous handler (if any)
820 AcpiEvDetachRegion (ObjDesc, FALSE);
823 * Then connect the region to the new handler
825 Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);