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