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