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