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