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