xref: /titanic_50/usr/src/uts/intel/io/acpica/events/evregion.c (revision e79c98e6c943cb3032f272714ff4ce6137d40394)
1 /******************************************************************************
2  *
3  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
4  *              $Revision: 1.166 $
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2006, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
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
20  * property rights.
21  *
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
28  *
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;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
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.
54  *
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
65  * make.
66  *
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
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
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.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
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
89  * PARTICULAR PURPOSE.
90  *
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
98  * LIMITED REMEDY.
99  *
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.
114  *
115  *****************************************************************************/
116 
117 
118 #define __EVREGION_C__
119 
120 #include "acpi.h"
121 #include "acevents.h"
122 #include "acnamesp.h"
123 #include "acinterp.h"
124 
125 #define _COMPONENT          ACPI_EVENTS
126         ACPI_MODULE_NAME    ("evregion")
127 
128 #define ACPI_NUM_DEFAULT_SPACES     4
129 
130 static UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
131 {
132     ACPI_ADR_SPACE_SYSTEM_MEMORY,
133     ACPI_ADR_SPACE_SYSTEM_IO,
134     ACPI_ADR_SPACE_PCI_CONFIG,
135     ACPI_ADR_SPACE_DATA_TABLE
136 };
137 
138 /* Local prototypes */
139 
140 static ACPI_STATUS
141 AcpiEvRegRun (
142     ACPI_HANDLE             ObjHandle,
143     UINT32                  Level,
144     void                    *Context,
145     void                    **ReturnValue);
146 
147 static ACPI_STATUS
148 AcpiEvInstallHandler (
149     ACPI_HANDLE             ObjHandle,
150     UINT32                  Level,
151     void                    *Context,
152     void                    **ReturnValue);
153 
154 
155 /*******************************************************************************
156  *
157  * FUNCTION:    AcpiEvInstallRegionHandlers
158  *
159  * PARAMETERS:  None
160  *
161  * RETURN:      Status
162  *
163  * DESCRIPTION: Installs the core subsystem default address space handlers.
164  *
165  ******************************************************************************/
166 
167 ACPI_STATUS
168 AcpiEvInstallRegionHandlers (
169     void)
170 {
171     ACPI_STATUS             Status;
172     ACPI_NATIVE_UINT        i;
173 
174 
175     ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
176 
177 
178     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
179     if (ACPI_FAILURE (Status))
180     {
181         return_ACPI_STATUS (Status);
182     }
183 
184     /*
185      * All address spaces (PCI Config, EC, SMBus) are scope dependent
186      * and registration must occur for a specific device.
187      *
188      * In the case of the system memory and IO address spaces there is currently
189      * no device associated with the address space.  For these we use the root.
190      *
191      * We install the default PCI config space handler at the root so
192      * that this space is immediately available even though the we have
193      * not enumerated all the PCI Root Buses yet.  This is to conform
194      * to the ACPI specification which states that the PCI config
195      * space must be always available -- even though we are nowhere
196      * near ready to find the PCI root buses at this point.
197      *
198      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
199      * has already been installed (via AcpiInstallAddressSpaceHandler).
200      * Similar for AE_SAME_HANDLER.
201      */
202     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
203     {
204         Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
205                     AcpiGbl_DefaultAddressSpaces[i],
206                     ACPI_DEFAULT_HANDLER, NULL, NULL);
207         switch (Status)
208         {
209         case AE_OK:
210         case AE_SAME_HANDLER:
211         case AE_ALREADY_EXISTS:
212 
213             /* These exceptions are all OK */
214 
215             Status = AE_OK;
216             break;
217 
218         default:
219 
220             goto UnlockAndExit;
221         }
222     }
223 
224 UnlockAndExit:
225     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
226     return_ACPI_STATUS (Status);
227 }
228 
229 
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiEvInitializeOpRegions
233  *
234  * PARAMETERS:  None
235  *
236  * RETURN:      Status
237  *
238  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
239  *              an installed default region handler.
240  *
241  ******************************************************************************/
242 
243 ACPI_STATUS
244 AcpiEvInitializeOpRegions (
245     void)
246 {
247     ACPI_STATUS             Status;
248     ACPI_NATIVE_UINT        i;
249 
250 
251     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
252 
253 
254     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
255     if (ACPI_FAILURE (Status))
256     {
257         return_ACPI_STATUS (Status);
258     }
259 
260     /*
261      * Run the _REG methods for OpRegions in each default address space
262      */
263     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
264     {
265         /* TBD: Make sure handler is the DEFAULT handler, otherwise
266          * _REG will have already been run.
267          */
268         Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
269                     AcpiGbl_DefaultAddressSpaces[i]);
270     }
271 
272     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
273     return_ACPI_STATUS (Status);
274 }
275 
276 
277 /*******************************************************************************
278  *
279  * FUNCTION:    AcpiEvExecuteRegMethod
280  *
281  * PARAMETERS:  RegionObj           - Region object
282  *              Function            - Passed to _REG: On (1) or Off (0)
283  *
284  * RETURN:      Status
285  *
286  * DESCRIPTION: Execute _REG method for a region
287  *
288  ******************************************************************************/
289 
290 ACPI_STATUS
291 AcpiEvExecuteRegMethod (
292     ACPI_OPERAND_OBJECT     *RegionObj,
293     UINT32                  Function)
294 {
295     ACPI_EVALUATE_INFO      *Info;
296     ACPI_OPERAND_OBJECT     *Args[3];
297     ACPI_OPERAND_OBJECT     *RegionObj2;
298     ACPI_STATUS             Status;
299 
300 
301     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
302 
303 
304     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
305     if (!RegionObj2)
306     {
307         return_ACPI_STATUS (AE_NOT_EXIST);
308     }
309 
310     if (RegionObj2->Extra.Method_REG == NULL)
311     {
312         return_ACPI_STATUS (AE_OK);
313     }
314 
315     /* Allocate and initialize the evaluation information block */
316 
317     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
318     if (!Info)
319     {
320         return_ACPI_STATUS (AE_NO_MEMORY);
321     }
322 
323     Info->PrefixNode = RegionObj2->Extra.Method_REG;
324     Info->Pathname = NULL;
325     Info->Parameters = Args;
326     Info->ParameterType = ACPI_PARAM_ARGS;
327     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
328 
329     /*
330      * The _REG method has two arguments:
331      *
332      * Arg0 - Integer:
333      *  Operation region space ID Same value as RegionObj->Region.SpaceId
334      *
335      * Arg1 - Integer:
336      *  connection status 1 for connecting the handler, 0 for disconnecting
337      *  the handler (Passed as a parameter)
338      */
339     Args[0] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
340     if (!Args[0])
341     {
342         Status = AE_NO_MEMORY;
343         goto Cleanup1;
344     }
345 
346     Args[1] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
347     if (!Args[1])
348     {
349         Status = AE_NO_MEMORY;
350         goto Cleanup2;
351     }
352 
353     /* Setup the parameter objects */
354 
355     Args[0]->Integer.Value = RegionObj->Region.SpaceId;
356     Args[1]->Integer.Value = Function;
357     Args[2] = NULL;
358 
359     /* Execute the method, no return value */
360 
361     ACPI_DEBUG_EXEC (
362         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
363 
364     Status = AcpiNsEvaluate (Info);
365     AcpiUtRemoveReference (Args[1]);
366 
367 Cleanup2:
368     AcpiUtRemoveReference (Args[0]);
369 
370 Cleanup1:
371     ACPI_FREE (Info);
372     return_ACPI_STATUS (Status);
373 }
374 
375 
376 /*******************************************************************************
377  *
378  * FUNCTION:    AcpiEvAddressSpaceDispatch
379  *
380  * PARAMETERS:  RegionObj           - Internal region object
381  *              Function            - Read or Write operation
382  *              Address             - Where in the space to read or write
383  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
384  *              Value               - Pointer to in or out value, must be
385  *                                    full 64-bit ACPI_INTEGER
386  *
387  * RETURN:      Status
388  *
389  * DESCRIPTION: Dispatch an address space or operation region access to
390  *              a previously installed handler.
391  *
392  ******************************************************************************/
393 
394 ACPI_STATUS
395 AcpiEvAddressSpaceDispatch (
396     ACPI_OPERAND_OBJECT     *RegionObj,
397     UINT32                  Function,
398     ACPI_PHYSICAL_ADDRESS   Address,
399     UINT32                  BitWidth,
400     ACPI_INTEGER            *Value)
401 {
402     ACPI_STATUS             Status;
403     ACPI_STATUS             Status2;
404     ACPI_ADR_SPACE_HANDLER  Handler;
405     ACPI_ADR_SPACE_SETUP    RegionSetup;
406     ACPI_OPERAND_OBJECT     *HandlerDesc;
407     ACPI_OPERAND_OBJECT     *RegionObj2;
408     void                    *RegionContext = NULL;
409 
410 
411     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
412 
413 
414     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
415     if (!RegionObj2)
416     {
417         return_ACPI_STATUS (AE_NOT_EXIST);
418     }
419 
420     /* Ensure that there is a handler associated with this region */
421 
422     HandlerDesc = RegionObj->Region.Handler;
423     if (!HandlerDesc)
424     {
425         ACPI_ERROR ((AE_INFO,
426             "No handler for Region [%4.4s] (%p) [%s]",
427             AcpiUtGetNodeName (RegionObj->Region.Node),
428             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
429 
430         return_ACPI_STATUS (AE_NOT_EXIST);
431     }
432 
433     /*
434      * It may be the case that the region has never been initialized
435      * Some types of regions require special init code
436      */
437     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
438     {
439         /*
440          * This region has not been initialized yet, do it
441          */
442         RegionSetup = HandlerDesc->AddressSpace.Setup;
443         if (!RegionSetup)
444         {
445             /* No initialization routine, exit with error */
446 
447             ACPI_ERROR ((AE_INFO,
448                 "No init routine for region(%p) [%s]",
449                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
450             return_ACPI_STATUS (AE_NOT_EXIST);
451         }
452 
453         /*
454          * We must exit the interpreter because the region
455          * setup will potentially execute control methods
456          * (e.g., _REG method for this region)
457          */
458         AcpiExExitInterpreter ();
459 
460         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
461                     HandlerDesc->AddressSpace.Context, &RegionContext);
462 
463         /* Re-enter the interpreter */
464 
465         Status2 = AcpiExEnterInterpreter ();
466         if (ACPI_FAILURE (Status2))
467         {
468             return_ACPI_STATUS (Status2);
469         }
470 
471         /* Check for failure of the Region Setup */
472 
473         if (ACPI_FAILURE (Status))
474         {
475             ACPI_EXCEPTION ((AE_INFO, Status,
476                 "During region initialization: [%s]",
477                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
478             return_ACPI_STATUS (Status);
479         }
480 
481         /*
482          * Region initialization may have been completed by RegionSetup
483          */
484         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
485         {
486             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
487 
488             if (RegionObj2->Extra.RegionContext)
489             {
490                 /* The handler for this region was already installed */
491 
492                 ACPI_FREE (RegionContext);
493             }
494             else
495             {
496                 /*
497                  * Save the returned context for use in all accesses to
498                  * this particular region
499                  */
500                 RegionObj2->Extra.RegionContext = RegionContext;
501             }
502         }
503     }
504 
505     /* We have everything we need, we can invoke the address space handler */
506 
507     Handler = HandlerDesc->AddressSpace.Handler;
508 
509     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
510         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
511         &RegionObj->Region.Handler->AddressSpace, Handler,
512         ACPI_FORMAT_UINT64 (Address),
513         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
514 
515     if (!(HandlerDesc->AddressSpace.HandlerFlags &
516             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
517     {
518         /*
519          * For handlers other than the default (supplied) handlers, we must
520          * exit the interpreter because the handler *might* block -- we don't
521          * know what it will do, so we can't hold the lock on the intepreter.
522          */
523         AcpiExExitInterpreter();
524     }
525 
526     /* Call the handler */
527 
528     Status = Handler (Function, Address, BitWidth, Value,
529         HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
530 
531     if (ACPI_FAILURE (Status))
532     {
533         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
534             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
535     }
536 
537     if (!(HandlerDesc->AddressSpace.HandlerFlags &
538             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
539     {
540         /*
541          * We just returned from a non-default handler, we must re-enter the
542          * interpreter
543          */
544         Status2 = AcpiExEnterInterpreter ();
545         if (ACPI_FAILURE (Status2))
546         {
547             return_ACPI_STATUS (Status2);
548         }
549     }
550 
551     return_ACPI_STATUS (Status);
552 }
553 
554 
555 /*******************************************************************************
556  *
557  * FUNCTION:    AcpiEvDetachRegion
558  *
559  * PARAMETERS:  RegionObj           - Region Object
560  *              AcpiNsIsLocked      - Namespace Region Already Locked?
561  *
562  * RETURN:      None
563  *
564  * DESCRIPTION: Break the association between the handler and the region
565  *              this is a two way association.
566  *
567  ******************************************************************************/
568 
569 void
570 AcpiEvDetachRegion(
571     ACPI_OPERAND_OBJECT     *RegionObj,
572     BOOLEAN                 AcpiNsIsLocked)
573 {
574     ACPI_OPERAND_OBJECT     *HandlerObj;
575     ACPI_OPERAND_OBJECT     *ObjDesc;
576     ACPI_OPERAND_OBJECT     **LastObjPtr;
577     ACPI_ADR_SPACE_SETUP    RegionSetup;
578     void                    **RegionContext;
579     ACPI_OPERAND_OBJECT     *RegionObj2;
580     ACPI_STATUS             Status;
581 
582 
583     ACPI_FUNCTION_TRACE (EvDetachRegion);
584 
585 
586     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
587     if (!RegionObj2)
588     {
589         return_VOID;
590     }
591     RegionContext = &RegionObj2->Extra.RegionContext;
592 
593     /* Get the address handler from the region object */
594 
595     HandlerObj = RegionObj->Region.Handler;
596     if (!HandlerObj)
597     {
598         /* This region has no handler, all done */
599 
600         return_VOID;
601     }
602 
603     /* Find this region in the handler's list */
604 
605     ObjDesc = HandlerObj->AddressSpace.RegionList;
606     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
607 
608     while (ObjDesc)
609     {
610         /* Is this the correct Region? */
611 
612         if (ObjDesc == RegionObj)
613         {
614             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
615                 "Removing Region %p from address handler %p\n",
616                 RegionObj, HandlerObj));
617 
618             /* This is it, remove it from the handler's list */
619 
620             *LastObjPtr = ObjDesc->Region.Next;
621             ObjDesc->Region.Next = NULL;            /* Must clear field */
622 
623             if (AcpiNsIsLocked)
624             {
625                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
626                 if (ACPI_FAILURE (Status))
627                 {
628                     return_VOID;
629                 }
630             }
631 
632             /* Now stop region accesses by executing the _REG method */
633 
634             Status = AcpiEvExecuteRegMethod (RegionObj, 0);
635             if (ACPI_FAILURE (Status))
636             {
637                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
638                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
639             }
640 
641             if (AcpiNsIsLocked)
642             {
643                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
644                 if (ACPI_FAILURE (Status))
645                 {
646                     return_VOID;
647                 }
648             }
649 
650             /*
651              * If the region has been activated, call the setup handler
652              * with the deactivate notification
653              */
654             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
655             {
656                 RegionSetup = HandlerObj->AddressSpace.Setup;
657                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
658                     HandlerObj->AddressSpace.Context, RegionContext);
659 
660                 /* Init routine may fail, Just ignore errors */
661 
662                 if (ACPI_FAILURE (Status))
663                 {
664                     ACPI_EXCEPTION ((AE_INFO, Status,
665                         "from region handler - deactivate, [%s]",
666                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
667                 }
668 
669                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
670             }
671 
672             /*
673              * Remove handler reference in the region
674              *
675              * NOTE: this doesn't mean that the region goes away, the region
676              * is just inaccessible as indicated to the _REG method
677              *
678              * If the region is on the handler's list, this must be the
679              * region's handler
680              */
681             RegionObj->Region.Handler = NULL;
682             AcpiUtRemoveReference (HandlerObj);
683 
684             return_VOID;
685         }
686 
687         /* Walk the linked list of handlers */
688 
689         LastObjPtr = &ObjDesc->Region.Next;
690         ObjDesc = ObjDesc->Region.Next;
691     }
692 
693     /* If we get here, the region was not in the handler's region list */
694 
695     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
696         "Cannot remove region %p from address handler %p\n",
697         RegionObj, HandlerObj));
698 
699     return_VOID;
700 }
701 
702 
703 /*******************************************************************************
704  *
705  * FUNCTION:    AcpiEvAttachRegion
706  *
707  * PARAMETERS:  HandlerObj          - Handler Object
708  *              RegionObj           - Region Object
709  *              AcpiNsIsLocked      - Namespace Region Already Locked?
710  *
711  * RETURN:      None
712  *
713  * DESCRIPTION: Create the association between the handler and the region
714  *              this is a two way association.
715  *
716  ******************************************************************************/
717 
718 ACPI_STATUS
719 AcpiEvAttachRegion (
720     ACPI_OPERAND_OBJECT     *HandlerObj,
721     ACPI_OPERAND_OBJECT     *RegionObj,
722     BOOLEAN                 AcpiNsIsLocked)
723 {
724 
725     ACPI_FUNCTION_TRACE (EvAttachRegion);
726 
727 
728     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
729         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
730         AcpiUtGetNodeName (RegionObj->Region.Node),
731         RegionObj, HandlerObj,
732         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
733 
734     /* Link this region to the front of the handler's list */
735 
736     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
737     HandlerObj->AddressSpace.RegionList = RegionObj;
738 
739     /* Install the region's handler */
740 
741     if (RegionObj->Region.Handler)
742     {
743         return_ACPI_STATUS (AE_ALREADY_EXISTS);
744     }
745 
746     RegionObj->Region.Handler = HandlerObj;
747     AcpiUtAddReference (HandlerObj);
748 
749     return_ACPI_STATUS (AE_OK);
750 }
751 
752 
753 /*******************************************************************************
754  *
755  * FUNCTION:    AcpiEvInstallHandler
756  *
757  * PARAMETERS:  WalkNamespace callback
758  *
759  * DESCRIPTION: This routine installs an address handler into objects that are
760  *              of type Region or Device.
761  *
762  *              If the Object is a Device, and the device has a handler of
763  *              the same type then the search is terminated in that branch.
764  *
765  *              This is because the existing handler is closer in proximity
766  *              to any more regions than the one we are trying to install.
767  *
768  ******************************************************************************/
769 
770 static ACPI_STATUS
771 AcpiEvInstallHandler (
772     ACPI_HANDLE             ObjHandle,
773     UINT32                  Level,
774     void                    *Context,
775     void                    **ReturnValue)
776 {
777     ACPI_OPERAND_OBJECT     *HandlerObj;
778     ACPI_OPERAND_OBJECT     *NextHandlerObj;
779     ACPI_OPERAND_OBJECT     *ObjDesc;
780     ACPI_NAMESPACE_NODE     *Node;
781     ACPI_STATUS             Status;
782 
783 
784     ACPI_FUNCTION_NAME (EvInstallHandler);
785 
786 
787     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
788 
789     /* Parameter validation */
790 
791     if (!HandlerObj)
792     {
793         return (AE_OK);
794     }
795 
796     /* Convert and validate the device handle */
797 
798     Node = AcpiNsMapHandleToNode (ObjHandle);
799     if (!Node)
800     {
801         return (AE_BAD_PARAMETER);
802     }
803 
804     /*
805      * We only care about regions.and objects
806      * that are allowed to have address space handlers
807      */
808     if ((Node->Type != ACPI_TYPE_DEVICE) &&
809         (Node->Type != ACPI_TYPE_REGION) &&
810         (Node != AcpiGbl_RootNode))
811     {
812         return (AE_OK);
813     }
814 
815     /* Check for an existing internal object */
816 
817     ObjDesc = AcpiNsGetAttachedObject (Node);
818     if (!ObjDesc)
819     {
820         /* No object, just exit */
821 
822         return (AE_OK);
823     }
824 
825     /* Devices are handled different than regions */
826 
827     if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_DEVICE)
828     {
829         /* Check if this Device already has a handler for this address space */
830 
831         NextHandlerObj = ObjDesc->Device.Handler;
832         while (NextHandlerObj)
833         {
834             /* Found a handler, is it for the same address space? */
835 
836             if (NextHandlerObj->AddressSpace.SpaceId == HandlerObj->AddressSpace.SpaceId)
837             {
838                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
839                     "Found handler for region [%s] in device %p(%p) handler %p\n",
840                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
841                     ObjDesc, NextHandlerObj, HandlerObj));
842 
843                 /*
844                  * Since the object we found it on was a device, then it
845                  * means that someone has already installed a handler for
846                  * the branch of the namespace from this device on.  Just
847                  * bail out telling the walk routine to not traverse this
848                  * branch.  This preserves the scoping rule for handlers.
849                  */
850                 return (AE_CTRL_DEPTH);
851             }
852 
853             /* Walk the linked list of handlers attached to this device */
854 
855             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
856         }
857 
858         /*
859          * As long as the device didn't have a handler for this
860          * space we don't care about it.  We just ignore it and
861          * proceed.
862          */
863         return (AE_OK);
864     }
865 
866     /* Object is a Region */
867 
868     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
869     {
870         /*
871          * This region is for a different address space
872          * -- just ignore it
873          */
874         return (AE_OK);
875     }
876 
877     /*
878      * Now we have a region and it is for the handler's address
879      * space type.
880      *
881      * First disconnect region for any previous handler (if any)
882      */
883     AcpiEvDetachRegion (ObjDesc, FALSE);
884 
885     /* Connect the region to the new handler */
886 
887     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
888     return (Status);
889 }
890 
891 
892 /*******************************************************************************
893  *
894  * FUNCTION:    AcpiEvInstallSpaceHandler
895  *
896  * PARAMETERS:  Node            - Namespace node for the device
897  *              SpaceId         - The address space ID
898  *              Handler         - Address of the handler
899  *              Setup           - Address of the setup function
900  *              Context         - Value passed to the handler on each access
901  *
902  * RETURN:      Status
903  *
904  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
905  *              Assumes namespace is locked
906  *
907  ******************************************************************************/
908 
909 ACPI_STATUS
910 AcpiEvInstallSpaceHandler (
911     ACPI_NAMESPACE_NODE     *Node,
912     ACPI_ADR_SPACE_TYPE     SpaceId,
913     ACPI_ADR_SPACE_HANDLER  Handler,
914     ACPI_ADR_SPACE_SETUP    Setup,
915     void                    *Context)
916 {
917     ACPI_OPERAND_OBJECT     *ObjDesc;
918     ACPI_OPERAND_OBJECT     *HandlerObj;
919     ACPI_STATUS             Status;
920     ACPI_OBJECT_TYPE        Type;
921     UINT8                  Flags = 0;
922 
923 
924     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
925 
926 
927     /*
928      * This registration is valid for only the types below
929      * and the root.  This is where the default handlers
930      * get placed.
931      */
932     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
933         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
934         (Node->Type != ACPI_TYPE_THERMAL)    &&
935         (Node != AcpiGbl_RootNode))
936     {
937         Status = AE_BAD_PARAMETER;
938         goto UnlockAndExit;
939     }
940 
941     if (Handler == ACPI_DEFAULT_HANDLER)
942     {
943         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
944 
945         switch (SpaceId)
946         {
947         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
948             Handler = AcpiExSystemMemorySpaceHandler;
949             Setup   = AcpiEvSystemMemoryRegionSetup;
950             break;
951 
952         case ACPI_ADR_SPACE_SYSTEM_IO:
953             Handler = AcpiExSystemIoSpaceHandler;
954             Setup   = AcpiEvIoSpaceRegionSetup;
955             break;
956 
957         case ACPI_ADR_SPACE_PCI_CONFIG:
958             Handler = AcpiExPciConfigSpaceHandler;
959             Setup   = AcpiEvPciConfigRegionSetup;
960             break;
961 
962         case ACPI_ADR_SPACE_CMOS:
963             Handler = AcpiExCmosSpaceHandler;
964             Setup   = AcpiEvCmosRegionSetup;
965             break;
966 
967         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
968             Handler = AcpiExPciBarSpaceHandler;
969             Setup   = AcpiEvPciBarRegionSetup;
970             break;
971 
972         case ACPI_ADR_SPACE_DATA_TABLE:
973             Handler = AcpiExDataTableSpaceHandler;
974             Setup   = NULL;
975             break;
976 
977         default:
978             Status = AE_BAD_PARAMETER;
979             goto UnlockAndExit;
980         }
981     }
982 
983     /* If the caller hasn't specified a setup routine, use the default */
984 
985     if (!Setup)
986     {
987         Setup = AcpiEvDefaultRegionSetup;
988     }
989 
990     /* Check for an existing internal object */
991 
992     ObjDesc = AcpiNsGetAttachedObject (Node);
993     if (ObjDesc)
994     {
995         /*
996          * The attached device object already exists.
997          * Make sure the handler is not already installed.
998          */
999         HandlerObj = ObjDesc->Device.Handler;
1000 
1001         /* Walk the handler list for this device */
1002 
1003         while (HandlerObj)
1004         {
1005             /* Same SpaceId indicates a handler already installed */
1006 
1007             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
1008             {
1009                 if (HandlerObj->AddressSpace.Handler == Handler)
1010                 {
1011                     /*
1012                      * It is (relatively) OK to attempt to install the SAME
1013                      * handler twice. This can easily happen
1014                      * with PCI_Config space.
1015                      */
1016                     Status = AE_SAME_HANDLER;
1017                     goto UnlockAndExit;
1018                 }
1019                 else
1020                 {
1021                     /* A handler is already installed */
1022 
1023                     Status = AE_ALREADY_EXISTS;
1024                 }
1025                 goto UnlockAndExit;
1026             }
1027 
1028             /* Walk the linked list of handlers */
1029 
1030             HandlerObj = HandlerObj->AddressSpace.Next;
1031         }
1032     }
1033     else
1034     {
1035         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1036             "Creating object on Device %p while installing handler\n", Node));
1037 
1038         /* ObjDesc does not exist, create one */
1039 
1040         if (Node->Type == ACPI_TYPE_ANY)
1041         {
1042             Type = ACPI_TYPE_DEVICE;
1043         }
1044         else
1045         {
1046             Type = Node->Type;
1047         }
1048 
1049         ObjDesc = AcpiUtCreateInternalObject (Type);
1050         if (!ObjDesc)
1051         {
1052             Status = AE_NO_MEMORY;
1053             goto UnlockAndExit;
1054         }
1055 
1056         /* Init new descriptor */
1057 
1058         ObjDesc->Common.Type = (UINT8) Type;
1059 
1060         /* Attach the new object to the Node */
1061 
1062         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
1063 
1064         /* Remove local reference to the object */
1065 
1066         AcpiUtRemoveReference (ObjDesc);
1067 
1068         if (ACPI_FAILURE (Status))
1069         {
1070             goto UnlockAndExit;
1071         }
1072     }
1073 
1074     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1075         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
1076         AcpiUtGetRegionName (SpaceId), SpaceId,
1077         AcpiUtGetNodeName (Node), Node, ObjDesc));
1078 
1079     /*
1080      * Install the handler
1081      *
1082      * At this point there is no existing handler.
1083      * Just allocate the object for the handler and link it
1084      * into the list.
1085      */
1086     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
1087     if (!HandlerObj)
1088     {
1089         Status = AE_NO_MEMORY;
1090         goto UnlockAndExit;
1091     }
1092 
1093     /* Init handler obj */
1094 
1095     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
1096     HandlerObj->AddressSpace.HandlerFlags = Flags;
1097     HandlerObj->AddressSpace.RegionList = NULL;
1098     HandlerObj->AddressSpace.Node = Node;
1099     HandlerObj->AddressSpace.Handler = Handler;
1100     HandlerObj->AddressSpace.Context = Context;
1101     HandlerObj->AddressSpace.Setup  = Setup;
1102 
1103     /* Install at head of Device.AddressSpace list */
1104 
1105     HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
1106 
1107     /*
1108      * The Device object is the first reference on the HandlerObj.
1109      * Each region that uses the handler adds a reference.
1110      */
1111     ObjDesc->Device.Handler = HandlerObj;
1112 
1113     /*
1114      * Walk the namespace finding all of the regions this
1115      * handler will manage.
1116      *
1117      * Start at the device and search the branch toward
1118      * the leaf nodes until either the leaf is encountered or
1119      * a device is detected that has an address handler of the
1120      * same type.
1121      *
1122      * In either case, back up and search down the remainder
1123      * of the branch
1124      */
1125     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1126                 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler,
1127                 HandlerObj, NULL);
1128 
1129 UnlockAndExit:
1130     return_ACPI_STATUS (Status);
1131 }
1132 
1133 
1134 /*******************************************************************************
1135  *
1136  * FUNCTION:    AcpiEvExecuteRegMethods
1137  *
1138  * PARAMETERS:  Node            - Namespace node for the device
1139  *              SpaceId         - The address space ID
1140  *
1141  * RETURN:      Status
1142  *
1143  * DESCRIPTION: Run all _REG methods for the input Space ID;
1144  *              Note: assumes namespace is locked, or system init time.
1145  *
1146  ******************************************************************************/
1147 
1148 ACPI_STATUS
1149 AcpiEvExecuteRegMethods (
1150     ACPI_NAMESPACE_NODE     *Node,
1151     ACPI_ADR_SPACE_TYPE     SpaceId)
1152 {
1153     ACPI_STATUS             Status;
1154 
1155 
1156     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
1157 
1158 
1159     /*
1160      * Run all _REG methods for all Operation Regions for this
1161      * space ID.  This is a separate walk in order to handle any
1162      * interdependencies between regions and _REG methods.  (i.e. handlers
1163      * must be installed for all regions of this Space ID before we
1164      * can run any _REG methods)
1165      */
1166     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1167                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun,
1168                 &SpaceId, NULL);
1169 
1170     return_ACPI_STATUS (Status);
1171 }
1172 
1173 
1174 /*******************************************************************************
1175  *
1176  * FUNCTION:    AcpiEvRegRun
1177  *
1178  * PARAMETERS:  WalkNamespace callback
1179  *
1180  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
1181  *
1182  ******************************************************************************/
1183 
1184 static ACPI_STATUS
1185 AcpiEvRegRun (
1186     ACPI_HANDLE             ObjHandle,
1187     UINT32                  Level,
1188     void                    *Context,
1189     void                    **ReturnValue)
1190 {
1191     ACPI_OPERAND_OBJECT     *ObjDesc;
1192     ACPI_NAMESPACE_NODE     *Node;
1193     ACPI_ADR_SPACE_TYPE     SpaceId;
1194     ACPI_STATUS             Status;
1195 
1196 
1197     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
1198 
1199     /* Convert and validate the device handle */
1200 
1201     Node = AcpiNsMapHandleToNode (ObjHandle);
1202     if (!Node)
1203     {
1204         return (AE_BAD_PARAMETER);
1205     }
1206 
1207     /*
1208      * We only care about regions.and objects
1209      * that are allowed to have address space handlers
1210      */
1211     if ((Node->Type != ACPI_TYPE_REGION) &&
1212         (Node != AcpiGbl_RootNode))
1213     {
1214         return (AE_OK);
1215     }
1216 
1217     /* Check for an existing internal object */
1218 
1219     ObjDesc = AcpiNsGetAttachedObject (Node);
1220     if (!ObjDesc)
1221     {
1222         /* No object, just exit */
1223 
1224         return (AE_OK);
1225     }
1226 
1227     /* Object is a Region */
1228 
1229     if (ObjDesc->Region.SpaceId != SpaceId)
1230     {
1231         /*
1232          * This region is for a different address space
1233          * -- just ignore it
1234          */
1235         return (AE_OK);
1236     }
1237 
1238     Status = AcpiEvExecuteRegMethod (ObjDesc, 1);
1239     return (Status);
1240 }
1241 
1242