xref: /titanic_44/usr/src/uts/intel/io/acpica/events/evregion.c (revision 2d6b5ea734bb47d251c82670646fde46af15fd69)
1 /******************************************************************************
2  *
3  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
4  *              $Revision: 1.171 $
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2008, 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     UINT32                  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     UINT32                  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->Flags = ACPI_IGNORE_RETURN_VALUE;
327 
328     /*
329      * The _REG method has two arguments:
330      *
331      * Arg0 - Integer:
332      *  Operation region space ID Same value as RegionObj->Region.SpaceId
333      *
334      * Arg1 - Integer:
335      *  connection status 1 for connecting the handler, 0 for disconnecting
336      *  the handler (Passed as a parameter)
337      */
338     Args[0] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
339     if (!Args[0])
340     {
341         Status = AE_NO_MEMORY;
342         goto Cleanup1;
343     }
344 
345     Args[1] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
346     if (!Args[1])
347     {
348         Status = AE_NO_MEMORY;
349         goto Cleanup2;
350     }
351 
352     /* Setup the parameter objects */
353 
354     Args[0]->Integer.Value = RegionObj->Region.SpaceId;
355     Args[1]->Integer.Value = Function;
356     Args[2] = NULL;
357 
358     /* Execute the method, no return value */
359 
360     ACPI_DEBUG_EXEC (
361         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
362 
363     Status = AcpiNsEvaluate (Info);
364     AcpiUtRemoveReference (Args[1]);
365 
366 Cleanup2:
367     AcpiUtRemoveReference (Args[0]);
368 
369 Cleanup1:
370     ACPI_FREE (Info);
371     return_ACPI_STATUS (Status);
372 }
373 
374 
375 /*******************************************************************************
376  *
377  * FUNCTION:    AcpiEvAddressSpaceDispatch
378  *
379  * PARAMETERS:  RegionObj           - Internal region object
380  *              Function            - Read or Write operation
381  *              Address             - Where in the space to read or write
382  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
383  *              Value               - Pointer to in or out value, must be
384  *                                    full 64-bit ACPI_INTEGER
385  *
386  * RETURN:      Status
387  *
388  * DESCRIPTION: Dispatch an address space or operation region access to
389  *              a previously installed handler.
390  *
391  ******************************************************************************/
392 
393 ACPI_STATUS
394 AcpiEvAddressSpaceDispatch (
395     ACPI_OPERAND_OBJECT     *RegionObj,
396     UINT32                  Function,
397     ACPI_PHYSICAL_ADDRESS   Address,
398     UINT32                  BitWidth,
399     ACPI_INTEGER            *Value)
400 {
401     ACPI_STATUS             Status;
402     ACPI_ADR_SPACE_HANDLER  Handler;
403     ACPI_ADR_SPACE_SETUP    RegionSetup;
404     ACPI_OPERAND_OBJECT     *HandlerDesc;
405     ACPI_OPERAND_OBJECT     *RegionObj2;
406     void                    *RegionContext = NULL;
407 
408 
409     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
410 
411 
412     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
413     if (!RegionObj2)
414     {
415         return_ACPI_STATUS (AE_NOT_EXIST);
416     }
417 
418     /* Ensure that there is a handler associated with this region */
419 
420     HandlerDesc = RegionObj->Region.Handler;
421     if (!HandlerDesc)
422     {
423         ACPI_ERROR ((AE_INFO,
424             "No handler for Region [%4.4s] (%p) [%s]",
425             AcpiUtGetNodeName (RegionObj->Region.Node),
426             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
427 
428         return_ACPI_STATUS (AE_NOT_EXIST);
429     }
430 
431     /*
432      * It may be the case that the region has never been initialized
433      * Some types of regions require special init code
434      */
435     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
436     {
437         /*
438          * This region has not been initialized yet, do it
439          */
440         RegionSetup = HandlerDesc->AddressSpace.Setup;
441         if (!RegionSetup)
442         {
443             /* No initialization routine, exit with error */
444 
445             ACPI_ERROR ((AE_INFO,
446                 "No init routine for region(%p) [%s]",
447                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
448             return_ACPI_STATUS (AE_NOT_EXIST);
449         }
450 
451         /*
452          * We must exit the interpreter because the region
453          * setup will potentially execute control methods
454          * (e.g., _REG method for this region)
455          */
456         AcpiExExitInterpreter ();
457 
458         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
459                     HandlerDesc->AddressSpace.Context, &RegionContext);
460 
461         /* Re-enter the interpreter */
462 
463         AcpiExEnterInterpreter ();
464 
465         /* Check for failure of the Region Setup */
466 
467         if (ACPI_FAILURE (Status))
468         {
469             ACPI_EXCEPTION ((AE_INFO, Status,
470                 "During region initialization: [%s]",
471                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
472             return_ACPI_STATUS (Status);
473         }
474 
475         /*
476          * Region initialization may have been completed by RegionSetup
477          */
478         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
479         {
480             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
481 
482             if (RegionObj2->Extra.RegionContext)
483             {
484                 /* The handler for this region was already installed */
485 
486                 ACPI_FREE (RegionContext);
487             }
488             else
489             {
490                 /*
491                  * Save the returned context for use in all accesses to
492                  * this particular region
493                  */
494                 RegionObj2->Extra.RegionContext = RegionContext;
495             }
496         }
497     }
498 
499     /* We have everything we need, we can invoke the address space handler */
500 
501     Handler = HandlerDesc->AddressSpace.Handler;
502 
503     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
504         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
505         &RegionObj->Region.Handler->AddressSpace, Handler,
506         ACPI_FORMAT_NATIVE_UINT (Address),
507         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
508 
509     if (!(HandlerDesc->AddressSpace.HandlerFlags &
510             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
511     {
512         /*
513          * For handlers other than the default (supplied) handlers, we must
514          * exit the interpreter because the handler *might* block -- we don't
515          * know what it will do, so we can't hold the lock on the intepreter.
516          */
517         AcpiExExitInterpreter();
518     }
519 
520     /* Call the handler */
521 
522     Status = Handler (Function, Address, BitWidth, Value,
523         HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
524 
525     if (ACPI_FAILURE (Status))
526     {
527         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
528             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
529     }
530 
531     if (!(HandlerDesc->AddressSpace.HandlerFlags &
532             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
533     {
534         /*
535          * We just returned from a non-default handler, we must re-enter the
536          * interpreter
537          */
538        AcpiExEnterInterpreter ();
539     }
540 
541     return_ACPI_STATUS (Status);
542 }
543 
544 
545 /*******************************************************************************
546  *
547  * FUNCTION:    AcpiEvDetachRegion
548  *
549  * PARAMETERS:  RegionObj           - Region Object
550  *              AcpiNsIsLocked      - Namespace Region Already Locked?
551  *
552  * RETURN:      None
553  *
554  * DESCRIPTION: Break the association between the handler and the region
555  *              this is a two way association.
556  *
557  ******************************************************************************/
558 
559 void
560 AcpiEvDetachRegion(
561     ACPI_OPERAND_OBJECT     *RegionObj,
562     BOOLEAN                 AcpiNsIsLocked)
563 {
564     ACPI_OPERAND_OBJECT     *HandlerObj;
565     ACPI_OPERAND_OBJECT     *ObjDesc;
566     ACPI_OPERAND_OBJECT     **LastObjPtr;
567     ACPI_ADR_SPACE_SETUP    RegionSetup;
568     void                    **RegionContext;
569     ACPI_OPERAND_OBJECT     *RegionObj2;
570     ACPI_STATUS             Status;
571 
572 
573     ACPI_FUNCTION_TRACE (EvDetachRegion);
574 
575 
576     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
577     if (!RegionObj2)
578     {
579         return_VOID;
580     }
581     RegionContext = &RegionObj2->Extra.RegionContext;
582 
583     /* Get the address handler from the region object */
584 
585     HandlerObj = RegionObj->Region.Handler;
586     if (!HandlerObj)
587     {
588         /* This region has no handler, all done */
589 
590         return_VOID;
591     }
592 
593     /* Find this region in the handler's list */
594 
595     ObjDesc = HandlerObj->AddressSpace.RegionList;
596     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
597 
598     while (ObjDesc)
599     {
600         /* Is this the correct Region? */
601 
602         if (ObjDesc == RegionObj)
603         {
604             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
605                 "Removing Region %p from address handler %p\n",
606                 RegionObj, HandlerObj));
607 
608             /* This is it, remove it from the handler's list */
609 
610             *LastObjPtr = ObjDesc->Region.Next;
611             ObjDesc->Region.Next = NULL;            /* Must clear field */
612 
613             if (AcpiNsIsLocked)
614             {
615                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
616                 if (ACPI_FAILURE (Status))
617                 {
618                     return_VOID;
619                 }
620             }
621 
622             /* Now stop region accesses by executing the _REG method */
623 
624             Status = AcpiEvExecuteRegMethod (RegionObj, 0);
625             if (ACPI_FAILURE (Status))
626             {
627                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
628                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
629             }
630 
631             if (AcpiNsIsLocked)
632             {
633                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
634                 if (ACPI_FAILURE (Status))
635                 {
636                     return_VOID;
637                 }
638             }
639 
640             /*
641              * If the region has been activated, call the setup handler
642              * with the deactivate notification
643              */
644             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
645             {
646                 RegionSetup = HandlerObj->AddressSpace.Setup;
647                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
648                     HandlerObj->AddressSpace.Context, RegionContext);
649 
650                 /* Init routine may fail, Just ignore errors */
651 
652                 if (ACPI_FAILURE (Status))
653                 {
654                     ACPI_EXCEPTION ((AE_INFO, Status,
655                         "from region handler - deactivate, [%s]",
656                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
657                 }
658 
659                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
660             }
661 
662             /*
663              * Remove handler reference in the region
664              *
665              * NOTE: this doesn't mean that the region goes away, the region
666              * is just inaccessible as indicated to the _REG method
667              *
668              * If the region is on the handler's list, this must be the
669              * region's handler
670              */
671             RegionObj->Region.Handler = NULL;
672             AcpiUtRemoveReference (HandlerObj);
673 
674             return_VOID;
675         }
676 
677         /* Walk the linked list of handlers */
678 
679         LastObjPtr = &ObjDesc->Region.Next;
680         ObjDesc = ObjDesc->Region.Next;
681     }
682 
683     /* If we get here, the region was not in the handler's region list */
684 
685     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
686         "Cannot remove region %p from address handler %p\n",
687         RegionObj, HandlerObj));
688 
689     return_VOID;
690 }
691 
692 
693 /*******************************************************************************
694  *
695  * FUNCTION:    AcpiEvAttachRegion
696  *
697  * PARAMETERS:  HandlerObj          - Handler Object
698  *              RegionObj           - Region Object
699  *              AcpiNsIsLocked      - Namespace Region Already Locked?
700  *
701  * RETURN:      None
702  *
703  * DESCRIPTION: Create the association between the handler and the region
704  *              this is a two way association.
705  *
706  ******************************************************************************/
707 
708 ACPI_STATUS
709 AcpiEvAttachRegion (
710     ACPI_OPERAND_OBJECT     *HandlerObj,
711     ACPI_OPERAND_OBJECT     *RegionObj,
712     BOOLEAN                 AcpiNsIsLocked)
713 {
714 
715     ACPI_FUNCTION_TRACE (EvAttachRegion);
716 
717 
718     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
719         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
720         AcpiUtGetNodeName (RegionObj->Region.Node),
721         RegionObj, HandlerObj,
722         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
723 
724     /* Link this region to the front of the handler's list */
725 
726     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
727     HandlerObj->AddressSpace.RegionList = RegionObj;
728 
729     /* Install the region's handler */
730 
731     if (RegionObj->Region.Handler)
732     {
733         return_ACPI_STATUS (AE_ALREADY_EXISTS);
734     }
735 
736     RegionObj->Region.Handler = HandlerObj;
737     AcpiUtAddReference (HandlerObj);
738 
739     return_ACPI_STATUS (AE_OK);
740 }
741 
742 
743 /*******************************************************************************
744  *
745  * FUNCTION:    AcpiEvInstallHandler
746  *
747  * PARAMETERS:  WalkNamespace callback
748  *
749  * DESCRIPTION: This routine installs an address handler into objects that are
750  *              of type Region or Device.
751  *
752  *              If the Object is a Device, and the device has a handler of
753  *              the same type then the search is terminated in that branch.
754  *
755  *              This is because the existing handler is closer in proximity
756  *              to any more regions than the one we are trying to install.
757  *
758  ******************************************************************************/
759 
760 static ACPI_STATUS
761 AcpiEvInstallHandler (
762     ACPI_HANDLE             ObjHandle,
763     UINT32                  Level,
764     void                    *Context,
765     void                    **ReturnValue)
766 {
767     ACPI_OPERAND_OBJECT     *HandlerObj;
768     ACPI_OPERAND_OBJECT     *NextHandlerObj;
769     ACPI_OPERAND_OBJECT     *ObjDesc;
770     ACPI_NAMESPACE_NODE     *Node;
771     ACPI_STATUS             Status;
772 
773 
774     ACPI_FUNCTION_NAME (EvInstallHandler);
775 
776 
777     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
778 
779     /* Parameter validation */
780 
781     if (!HandlerObj)
782     {
783         return (AE_OK);
784     }
785 
786     /* Convert and validate the device handle */
787 
788     Node = AcpiNsMapHandleToNode (ObjHandle);
789     if (!Node)
790     {
791         return (AE_BAD_PARAMETER);
792     }
793 
794     /*
795      * We only care about regions.and objects
796      * that are allowed to have address space handlers
797      */
798     if ((Node->Type != ACPI_TYPE_DEVICE) &&
799         (Node->Type != ACPI_TYPE_REGION) &&
800         (Node != AcpiGbl_RootNode))
801     {
802         return (AE_OK);
803     }
804 
805     /* Check for an existing internal object */
806 
807     ObjDesc = AcpiNsGetAttachedObject (Node);
808     if (!ObjDesc)
809     {
810         /* No object, just exit */
811 
812         return (AE_OK);
813     }
814 
815     /* Devices are handled different than regions */
816 
817     if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_DEVICE)
818     {
819         /* Check if this Device already has a handler for this address space */
820 
821         NextHandlerObj = ObjDesc->Device.Handler;
822         while (NextHandlerObj)
823         {
824             /* Found a handler, is it for the same address space? */
825 
826             if (NextHandlerObj->AddressSpace.SpaceId == HandlerObj->AddressSpace.SpaceId)
827             {
828                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
829                     "Found handler for region [%s] in device %p(%p) handler %p\n",
830                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
831                     ObjDesc, NextHandlerObj, HandlerObj));
832 
833                 /*
834                  * Since the object we found it on was a device, then it
835                  * means that someone has already installed a handler for
836                  * the branch of the namespace from this device on.  Just
837                  * bail out telling the walk routine to not traverse this
838                  * branch.  This preserves the scoping rule for handlers.
839                  */
840                 return (AE_CTRL_DEPTH);
841             }
842 
843             /* Walk the linked list of handlers attached to this device */
844 
845             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
846         }
847 
848         /*
849          * As long as the device didn't have a handler for this
850          * space we don't care about it.  We just ignore it and
851          * proceed.
852          */
853         return (AE_OK);
854     }
855 
856     /* Object is a Region */
857 
858     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
859     {
860         /*
861          * This region is for a different address space
862          * -- just ignore it
863          */
864         return (AE_OK);
865     }
866 
867     /*
868      * Now we have a region and it is for the handler's address
869      * space type.
870      *
871      * First disconnect region for any previous handler (if any)
872      */
873     AcpiEvDetachRegion (ObjDesc, FALSE);
874 
875     /* Connect the region to the new handler */
876 
877     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
878     return (Status);
879 }
880 
881 
882 /*******************************************************************************
883  *
884  * FUNCTION:    AcpiEvInstallSpaceHandler
885  *
886  * PARAMETERS:  Node            - Namespace node for the device
887  *              SpaceId         - The address space ID
888  *              Handler         - Address of the handler
889  *              Setup           - Address of the setup function
890  *              Context         - Value passed to the handler on each access
891  *
892  * RETURN:      Status
893  *
894  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
895  *              Assumes namespace is locked
896  *
897  ******************************************************************************/
898 
899 ACPI_STATUS
900 AcpiEvInstallSpaceHandler (
901     ACPI_NAMESPACE_NODE     *Node,
902     ACPI_ADR_SPACE_TYPE     SpaceId,
903     ACPI_ADR_SPACE_HANDLER  Handler,
904     ACPI_ADR_SPACE_SETUP    Setup,
905     void                    *Context)
906 {
907     ACPI_OPERAND_OBJECT     *ObjDesc;
908     ACPI_OPERAND_OBJECT     *HandlerObj;
909     ACPI_STATUS             Status;
910     ACPI_OBJECT_TYPE        Type;
911     UINT8                  Flags = 0;
912 
913 
914     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
915 
916 
917     /*
918      * This registration is valid for only the types below
919      * and the root.  This is where the default handlers
920      * get placed.
921      */
922     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
923         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
924         (Node->Type != ACPI_TYPE_THERMAL)    &&
925         (Node != AcpiGbl_RootNode))
926     {
927         Status = AE_BAD_PARAMETER;
928         goto UnlockAndExit;
929     }
930 
931     if (Handler == ACPI_DEFAULT_HANDLER)
932     {
933         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
934 
935         switch (SpaceId)
936         {
937         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
938             Handler = AcpiExSystemMemorySpaceHandler;
939             Setup   = AcpiEvSystemMemoryRegionSetup;
940             break;
941 
942         case ACPI_ADR_SPACE_SYSTEM_IO:
943             Handler = AcpiExSystemIoSpaceHandler;
944             Setup   = AcpiEvIoSpaceRegionSetup;
945             break;
946 
947         case ACPI_ADR_SPACE_PCI_CONFIG:
948             Handler = AcpiExPciConfigSpaceHandler;
949             Setup   = AcpiEvPciConfigRegionSetup;
950             break;
951 
952         case ACPI_ADR_SPACE_CMOS:
953             Handler = AcpiExCmosSpaceHandler;
954             Setup   = AcpiEvCmosRegionSetup;
955             break;
956 
957         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
958             Handler = AcpiExPciBarSpaceHandler;
959             Setup   = AcpiEvPciBarRegionSetup;
960             break;
961 
962         case ACPI_ADR_SPACE_DATA_TABLE:
963             Handler = AcpiExDataTableSpaceHandler;
964             Setup   = NULL;
965             break;
966 
967         default:
968             Status = AE_BAD_PARAMETER;
969             goto UnlockAndExit;
970         }
971     }
972 
973     /* If the caller hasn't specified a setup routine, use the default */
974 
975     if (!Setup)
976     {
977         Setup = AcpiEvDefaultRegionSetup;
978     }
979 
980     /* Check for an existing internal object */
981 
982     ObjDesc = AcpiNsGetAttachedObject (Node);
983     if (ObjDesc)
984     {
985         /*
986          * The attached device object already exists.
987          * Make sure the handler is not already installed.
988          */
989         HandlerObj = ObjDesc->Device.Handler;
990 
991         /* Walk the handler list for this device */
992 
993         while (HandlerObj)
994         {
995             /* Same SpaceId indicates a handler already installed */
996 
997             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
998             {
999                 if (HandlerObj->AddressSpace.Handler == Handler)
1000                 {
1001                     /*
1002                      * It is (relatively) OK to attempt to install the SAME
1003                      * handler twice. This can easily happen
1004                      * with PCI_Config space.
1005                      */
1006                     Status = AE_SAME_HANDLER;
1007                     goto UnlockAndExit;
1008                 }
1009                 else
1010                 {
1011                     /* A handler is already installed */
1012 
1013                     Status = AE_ALREADY_EXISTS;
1014                 }
1015                 goto UnlockAndExit;
1016             }
1017 
1018             /* Walk the linked list of handlers */
1019 
1020             HandlerObj = HandlerObj->AddressSpace.Next;
1021         }
1022     }
1023     else
1024     {
1025         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1026             "Creating object on Device %p while installing handler\n", Node));
1027 
1028         /* ObjDesc does not exist, create one */
1029 
1030         if (Node->Type == ACPI_TYPE_ANY)
1031         {
1032             Type = ACPI_TYPE_DEVICE;
1033         }
1034         else
1035         {
1036             Type = Node->Type;
1037         }
1038 
1039         ObjDesc = AcpiUtCreateInternalObject (Type);
1040         if (!ObjDesc)
1041         {
1042             Status = AE_NO_MEMORY;
1043             goto UnlockAndExit;
1044         }
1045 
1046         /* Init new descriptor */
1047 
1048         ObjDesc->Common.Type = (UINT8) Type;
1049 
1050         /* Attach the new object to the Node */
1051 
1052         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
1053 
1054         /* Remove local reference to the object */
1055 
1056         AcpiUtRemoveReference (ObjDesc);
1057 
1058         if (ACPI_FAILURE (Status))
1059         {
1060             goto UnlockAndExit;
1061         }
1062     }
1063 
1064     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1065         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
1066         AcpiUtGetRegionName (SpaceId), SpaceId,
1067         AcpiUtGetNodeName (Node), Node, ObjDesc));
1068 
1069     /*
1070      * Install the handler
1071      *
1072      * At this point there is no existing handler.
1073      * Just allocate the object for the handler and link it
1074      * into the list.
1075      */
1076     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
1077     if (!HandlerObj)
1078     {
1079         Status = AE_NO_MEMORY;
1080         goto UnlockAndExit;
1081     }
1082 
1083     /* Init handler obj */
1084 
1085     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
1086     HandlerObj->AddressSpace.HandlerFlags = Flags;
1087     HandlerObj->AddressSpace.RegionList = NULL;
1088     HandlerObj->AddressSpace.Node = Node;
1089     HandlerObj->AddressSpace.Handler = Handler;
1090     HandlerObj->AddressSpace.Context = Context;
1091     HandlerObj->AddressSpace.Setup  = Setup;
1092 
1093     /* Install at head of Device.AddressSpace list */
1094 
1095     HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
1096 
1097     /*
1098      * The Device object is the first reference on the HandlerObj.
1099      * Each region that uses the handler adds a reference.
1100      */
1101     ObjDesc->Device.Handler = HandlerObj;
1102 
1103     /*
1104      * Walk the namespace finding all of the regions this
1105      * handler will manage.
1106      *
1107      * Start at the device and search the branch toward
1108      * the leaf nodes until either the leaf is encountered or
1109      * a device is detected that has an address handler of the
1110      * same type.
1111      *
1112      * In either case, back up and search down the remainder
1113      * of the branch
1114      */
1115     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1116                 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler,
1117                 HandlerObj, NULL);
1118 
1119 UnlockAndExit:
1120     return_ACPI_STATUS (Status);
1121 }
1122 
1123 
1124 /*******************************************************************************
1125  *
1126  * FUNCTION:    AcpiEvExecuteRegMethods
1127  *
1128  * PARAMETERS:  Node            - Namespace node for the device
1129  *              SpaceId         - The address space ID
1130  *
1131  * RETURN:      Status
1132  *
1133  * DESCRIPTION: Run all _REG methods for the input Space ID;
1134  *              Note: assumes namespace is locked, or system init time.
1135  *
1136  ******************************************************************************/
1137 
1138 ACPI_STATUS
1139 AcpiEvExecuteRegMethods (
1140     ACPI_NAMESPACE_NODE     *Node,
1141     ACPI_ADR_SPACE_TYPE     SpaceId)
1142 {
1143     ACPI_STATUS             Status;
1144 
1145 
1146     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
1147 
1148 
1149     /*
1150      * Run all _REG methods for all Operation Regions for this
1151      * space ID.  This is a separate walk in order to handle any
1152      * interdependencies between regions and _REG methods.  (i.e. handlers
1153      * must be installed for all regions of this Space ID before we
1154      * can run any _REG methods)
1155      */
1156     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1157                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun,
1158                 &SpaceId, NULL);
1159 
1160     return_ACPI_STATUS (Status);
1161 }
1162 
1163 
1164 /*******************************************************************************
1165  *
1166  * FUNCTION:    AcpiEvRegRun
1167  *
1168  * PARAMETERS:  WalkNamespace callback
1169  *
1170  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
1171  *
1172  ******************************************************************************/
1173 
1174 static ACPI_STATUS
1175 AcpiEvRegRun (
1176     ACPI_HANDLE             ObjHandle,
1177     UINT32                  Level,
1178     void                    *Context,
1179     void                    **ReturnValue)
1180 {
1181     ACPI_OPERAND_OBJECT     *ObjDesc;
1182     ACPI_NAMESPACE_NODE     *Node;
1183     ACPI_ADR_SPACE_TYPE     SpaceId;
1184     ACPI_STATUS             Status;
1185 
1186 
1187     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
1188 
1189     /* Convert and validate the device handle */
1190 
1191     Node = AcpiNsMapHandleToNode (ObjHandle);
1192     if (!Node)
1193     {
1194         return (AE_BAD_PARAMETER);
1195     }
1196 
1197     /*
1198      * We only care about regions.and objects
1199      * that are allowed to have address space handlers
1200      */
1201     if ((Node->Type != ACPI_TYPE_REGION) &&
1202         (Node != AcpiGbl_RootNode))
1203     {
1204         return (AE_OK);
1205     }
1206 
1207     /* Check for an existing internal object */
1208 
1209     ObjDesc = AcpiNsGetAttachedObject (Node);
1210     if (!ObjDesc)
1211     {
1212         /* No object, just exit */
1213 
1214         return (AE_OK);
1215     }
1216 
1217     /* Object is a Region */
1218 
1219     if (ObjDesc->Region.SpaceId != SpaceId)
1220     {
1221         /*
1222          * This region is for a different address space
1223          * -- just ignore it
1224          */
1225         return (AE_OK);
1226     }
1227 
1228     Status = AcpiEvExecuteRegMethod (ObjDesc, 1);
1229     return (Status);
1230 }
1231 
1232