Bring in acpica-unix-20031203. As with other contrib imports, this import
[dragonfly.git] / sys / contrib / dev / acpica-unix-20031203 / events / evregion.c
1 /******************************************************************************
2  *
3  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
4  *              $Revision: 146 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2003, 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 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:    AcpiEvInitAddressSpaces
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 AcpiEvInitAddressSpaces (
151     void)
152 {
153     ACPI_STATUS             Status;
154     ACPI_NATIVE_UINT        i;
155
156
157     ACPI_FUNCTION_TRACE ("EvInitAddressSpaces");
158
159
160     /*
161      * All address spaces (PCI Config, EC, SMBus) are scope dependent
162      * and registration must occur for a specific device.
163      *
164      * In the case of the system memory and IO address spaces there is currently
165      * no device associated with the address space.  For these we use the root.
166      *
167      * We install the default PCI config space handler at the root so
168      * that this space is immediately available even though the we have
169      * not enumerated all the PCI Root Buses yet.  This is to conform
170      * to the ACPI specification which states that the PCI config
171      * space must be always available -- even though we are nowhere
172      * near ready to find the PCI root buses at this point.
173      *
174      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
175      * has already been installed (via AcpiInstallAddressSpaceHandler).
176      * Similar for AE_SAME_HANDLER.
177      */
178
179     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
180     {
181         Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
182                         AcpiGbl_DefaultAddressSpaces[i],
183                         ACPI_DEFAULT_HANDLER, NULL, NULL);
184         switch (Status)
185         {
186         case AE_OK:
187         case AE_SAME_HANDLER:
188         case AE_ALREADY_EXISTS:
189
190             /* These exceptions are all OK */
191
192             break;
193
194         default:
195
196             return_ACPI_STATUS (Status);
197         }
198     }
199
200     return_ACPI_STATUS (AE_OK);
201 }
202
203
204 /*******************************************************************************
205  *
206  * FUNCTION:    AcpiEvExecuteRegMethod
207  *
208  * PARAMETERS:  RegionObj           - Object structure
209  *              Function            - On (1) or Off (0)
210  *
211  * RETURN:      Status
212  *
213  * DESCRIPTION: Execute _REG method for a region
214  *
215  ******************************************************************************/
216
217 ACPI_STATUS
218 AcpiEvExecuteRegMethod (
219     ACPI_OPERAND_OBJECT    *RegionObj,
220     UINT32                  Function)
221 {
222     ACPI_OPERAND_OBJECT    *Params[3];
223     ACPI_OPERAND_OBJECT    *RegionObj2;
224     ACPI_STATUS             Status;
225
226
227     ACPI_FUNCTION_TRACE ("EvExecuteRegMethod");
228
229
230     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
231     if (!RegionObj2)
232     {
233         return_ACPI_STATUS (AE_NOT_EXIST);
234     }
235
236     if (RegionObj2->Extra.Method_REG == NULL)
237     {
238         return_ACPI_STATUS (AE_OK);
239     }
240
241     /*
242      * _REG method has two arguments
243      * Arg0:   Integer: Operation region space ID
244      *          Same value as RegionObj->Region.SpaceId
245      * Arg1:   Integer: connection status
246      *          1 for connecting the handler,
247      *          0 for disconnecting the handler
248      *          Passed as a parameter
249      */
250     Params[0] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
251     if (!Params[0])
252     {
253         return_ACPI_STATUS (AE_NO_MEMORY);
254     }
255
256     Params[1] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
257     if (!Params[1])
258     {
259         Status = AE_NO_MEMORY;
260         goto Cleanup;
261     }
262
263     /* Set up the parameter objects */
264
265     Params[0]->Integer.Value = RegionObj->Region.SpaceId;
266     Params[1]->Integer.Value = Function;
267     Params[2] = NULL;
268
269     /* Execute the method, no return value */
270
271     ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, RegionObj2->Extra.Method_REG, NULL));
272     Status = AcpiNsEvaluateByHandle (RegionObj2->Extra.Method_REG, Params, NULL);
273
274     AcpiUtRemoveReference (Params[1]);
275
276 Cleanup:
277     AcpiUtRemoveReference (Params[0]);
278
279     return_ACPI_STATUS (Status);
280 }
281
282
283 /*******************************************************************************
284  *
285  * FUNCTION:    AcpiEvAddressSpaceDispatch
286  *
287  * PARAMETERS:  RegionObj           - Internal region object
288  *              SpaceId             - ID of the address space (0-255)
289  *              Function            - Read or Write operation
290  *              Address             - Where in the space to read or write
291  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
292  *              Value               - Pointer to in or out value
293  *
294  * RETURN:      Status
295  *
296  * DESCRIPTION: Dispatch an address space or operation region access to
297  *              a previously installed handler.
298  *
299  ******************************************************************************/
300
301 ACPI_STATUS
302 AcpiEvAddressSpaceDispatch (
303     ACPI_OPERAND_OBJECT     *RegionObj,
304     UINT32                  Function,
305     ACPI_PHYSICAL_ADDRESS   Address,
306     UINT32                  BitWidth,
307     void                    *Value)
308 {
309     ACPI_STATUS             Status;
310     ACPI_STATUS             Status2;
311     ACPI_ADR_SPACE_HANDLER  Handler;
312     ACPI_ADR_SPACE_SETUP    RegionSetup;
313     ACPI_OPERAND_OBJECT     *HandlerDesc;
314     ACPI_OPERAND_OBJECT     *RegionObj2;
315     void                    *RegionContext = NULL;
316
317
318     ACPI_FUNCTION_TRACE ("EvAddressSpaceDispatch");
319
320
321     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
322     if (!RegionObj2)
323     {
324         return_ACPI_STATUS (AE_NOT_EXIST);
325     }
326
327     /* Ensure that there is a handler associated with this region */
328
329     HandlerDesc = RegionObj->Region.Handler;
330     if (!HandlerDesc)
331     {
332         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 
333             "No handler for Region [%4.4s] (%p) [%s]\n",
334             AcpiUtGetNodeName (RegionObj->Region.Node),
335             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
336
337         return_ACPI_STATUS (AE_NOT_EXIST);
338     }
339
340     /*
341      * It may be the case that the region has never been initialized
342      * Some types of regions require special init code
343      */
344     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
345     {
346         /*
347          * This region has not been initialized yet, do it
348          */
349         RegionSetup = HandlerDesc->AddressSpace.Setup;
350         if (!RegionSetup)
351         {
352             /* No initialization routine, exit with error */
353
354             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
355                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
356             return_ACPI_STATUS (AE_NOT_EXIST);
357         }
358
359         /*
360          * We must exit the interpreter because the region setup will potentially
361          * execute control methods (e.g., _REG method for this region)
362          */
363         AcpiExExitInterpreter ();
364
365         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
366                         HandlerDesc->AddressSpace.Context, &RegionContext);
367
368         /* Re-enter the interpreter */
369
370         Status2 = AcpiExEnterInterpreter ();
371         if (ACPI_FAILURE (Status2))
372         {
373             return_ACPI_STATUS (Status2);
374         }
375
376         /* Check for failure of the Region Setup */
377
378         if (ACPI_FAILURE (Status))
379         {
380             ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
381                 AcpiFormatException (Status),
382                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
383             return_ACPI_STATUS (Status);
384         }
385
386         /*
387          * Region initialization may have been completed by RegionSetup
388          */
389         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
390         {
391             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
392
393             if (RegionObj2->Extra.RegionContext)
394             {
395                 /* The handler for this region was already installed */
396
397                 ACPI_MEM_FREE (RegionContext);
398             }
399             else
400             {
401                 /*
402                  * Save the returned context for use in all accesses to
403                  * this particular region
404                  */
405                 RegionObj2->Extra.RegionContext = RegionContext;
406             }
407         }
408     }
409
410     /* We have everything we need, we can invoke the address space handler */
411
412     Handler = HandlerDesc->AddressSpace.Handler;
413
414     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
415         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
416         &RegionObj->Region.Handler->AddressSpace, Handler,
417         ACPI_FORMAT_UINT64 (Address),
418         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
419
420     if (!(HandlerDesc->AddressSpace.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
421     {
422         /*
423          * For handlers other than the default (supplied) handlers, we must
424          * exit the interpreter because the handler *might* block -- we don't
425          * know what it will do, so we can't hold the lock on the intepreter.
426          */
427         AcpiExExitInterpreter();
428     }
429
430     /* Call the handler */
431
432     Status = Handler (Function, Address, BitWidth, Value,
433                       HandlerDesc->AddressSpace.Context,
434                       RegionObj2->Extra.RegionContext);
435
436     if (ACPI_FAILURE (Status))
437     {
438         ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
439             AcpiUtGetRegionName (RegionObj->Region.SpaceId),
440             AcpiFormatException (Status)));
441     }
442
443     if (!(HandlerDesc->AddressSpace.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
444     {
445         /*
446          * We just returned from a non-default handler, we must re-enter the
447          * interpreter
448          */
449         Status2 = AcpiExEnterInterpreter ();
450         if (ACPI_FAILURE (Status2))
451         {
452             return_ACPI_STATUS (Status2);
453         }
454     }
455
456     return_ACPI_STATUS (Status);
457 }
458
459
460 /*******************************************************************************
461  *
462  * FUNCTION:    AcpiEvDetachRegion
463  *
464  * PARAMETERS:  RegionObj       - Region Object
465  *              AcpiNsIsLocked  - Namespace Region Already Locked?
466  *
467  * RETURN:      None
468  *
469  * DESCRIPTION: Break the association between the handler and the region
470  *              this is a two way association.
471  *
472  ******************************************************************************/
473
474 void
475 AcpiEvDetachRegion(
476     ACPI_OPERAND_OBJECT     *RegionObj,
477     BOOLEAN                 AcpiNsIsLocked)
478 {
479     ACPI_OPERAND_OBJECT     *HandlerObj;
480     ACPI_OPERAND_OBJECT     *ObjDesc;
481     ACPI_OPERAND_OBJECT     **LastObjPtr;
482     ACPI_ADR_SPACE_SETUP    RegionSetup;
483     void                    **RegionContext;
484     ACPI_OPERAND_OBJECT     *RegionObj2;
485     ACPI_STATUS             Status;
486
487
488     ACPI_FUNCTION_TRACE ("EvDetachRegion");
489
490
491     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
492     if (!RegionObj2)
493     {
494         return_VOID;
495     }
496     RegionContext = &RegionObj2->Extra.RegionContext;
497
498     /* Get the address handler from the region object */
499
500     HandlerObj = RegionObj->Region.Handler;
501     if (!HandlerObj)
502     {
503         /* This region has no handler, all done */
504
505         return_VOID;
506     }
507
508     /* Find this region in the handler's list */
509
510     ObjDesc = HandlerObj->AddressSpace.RegionList;
511     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
512
513     while (ObjDesc)
514     {
515         /* Is this the correct Region? */
516
517         if (ObjDesc == RegionObj)
518         {
519             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
520                 "Removing Region %p from address handler %p\n",
521                 RegionObj, HandlerObj));
522
523             /* This is it, remove it from the handler's list */
524
525             *LastObjPtr = ObjDesc->Region.Next;
526             ObjDesc->Region.Next = NULL;            /* Must clear field */
527
528             if (AcpiNsIsLocked)
529             {
530                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
531                 if (ACPI_FAILURE (Status))
532                 {
533                     return_VOID;
534                 }
535             }
536
537             /* Now stop region accesses by executing the _REG method */
538
539             Status = AcpiEvExecuteRegMethod (RegionObj, 0);
540             if (ACPI_FAILURE (Status))
541             {
542                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
543                     AcpiFormatException (Status),
544                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
545             }
546
547             if (AcpiNsIsLocked)
548             {
549                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
550                 if (ACPI_FAILURE (Status))
551                 {
552                     return_VOID;
553                 }
554             }
555
556             /* Call the setup handler with the deactivate notification */
557
558             RegionSetup = HandlerObj->AddressSpace.Setup;
559             Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
560                             HandlerObj->AddressSpace.Context, RegionContext);
561
562             /* Init routine may fail, Just ignore errors */
563
564             if (ACPI_FAILURE (Status))
565             {
566                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
567                     AcpiFormatException (Status),
568                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
569             }
570
571             RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
572
573             /*
574              * Remove handler reference in the region
575              *
576              * NOTE: this doesn't mean that the region goes away
577              * The region is just inaccessible as indicated to
578              * the _REG method
579              *
580              * If the region is on the handler's list
581              * this better be the region's handler
582              */
583             RegionObj->Region.Handler = NULL;
584             AcpiUtRemoveReference (HandlerObj);
585
586             return_VOID;
587         }
588
589         /* Walk the linked list of handlers */
590
591         LastObjPtr = &ObjDesc->Region.Next;
592         ObjDesc = ObjDesc->Region.Next;
593     }
594
595     /* If we get here, the region was not in the handler's region list */
596
597     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
598         "Cannot remove region %p from address handler %p\n",
599         RegionObj, HandlerObj));
600
601     return_VOID;
602 }
603
604
605 /*******************************************************************************
606  *
607  * FUNCTION:    AcpiEvAttachRegion
608  *
609  * PARAMETERS:  HandlerObj      - Handler Object
610  *              RegionObj       - Region Object
611  *              AcpiNsIsLocked  - Namespace Region Already Locked?
612  *
613  * RETURN:      None
614  *
615  * DESCRIPTION: Create the association between the handler and the region
616  *              this is a two way association.
617  *
618  ******************************************************************************/
619
620 ACPI_STATUS
621 AcpiEvAttachRegion (
622     ACPI_OPERAND_OBJECT     *HandlerObj,
623     ACPI_OPERAND_OBJECT     *RegionObj,
624     BOOLEAN                 AcpiNsIsLocked)
625 {
626
627     ACPI_FUNCTION_TRACE ("EvAttachRegion");
628
629
630     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
631         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
632         AcpiUtGetNodeName (RegionObj->Region.Node),
633         RegionObj, HandlerObj, 
634         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
635
636     /* Link this region to the front of the handler's list */
637
638     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
639     HandlerObj->AddressSpace.RegionList = RegionObj;
640
641     /* Install the region's handler */
642
643     if (RegionObj->Region.Handler)
644     {
645         return_ACPI_STATUS (AE_ALREADY_EXISTS);
646     }
647
648     RegionObj->Region.Handler = HandlerObj;
649     AcpiUtAddReference (HandlerObj);
650
651     return_ACPI_STATUS (AE_OK);
652 }
653
654
655 /*******************************************************************************
656  *
657  * FUNCTION:    AcpiEvInstallHandler
658  *
659  * PARAMETERS:  WalkNamespace callback
660  *
661  * DESCRIPTION: This routine installs an address handler into objects that are
662  *              of type Region or Device.
663  *
664  *              If the Object is a Device, and the device has a handler of
665  *              the same type then the search is terminated in that branch.
666  *
667  *              This is because the existing handler is closer in proximity
668  *              to any more regions than the one we are trying to install.
669  *
670  ******************************************************************************/
671
672 ACPI_STATUS
673 AcpiEvInstallHandler (
674     ACPI_HANDLE             ObjHandle,
675     UINT32                  Level,
676     void                    *Context,
677     void                    **ReturnValue)
678 {
679     ACPI_OPERAND_OBJECT     *HandlerObj;
680     ACPI_OPERAND_OBJECT     *NextHandlerObj;
681     ACPI_OPERAND_OBJECT     *ObjDesc;
682     ACPI_NAMESPACE_NODE     *Node;
683     ACPI_STATUS             Status;
684
685
686     ACPI_FUNCTION_NAME ("EvInstallHandler");
687
688
689     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
690
691     /* Parameter validation */
692
693     if (!HandlerObj)
694     {
695         return (AE_OK);
696     }
697
698     /* Convert and validate the device handle */
699
700     Node = AcpiNsMapHandleToNode (ObjHandle);
701     if (!Node)
702     {
703         return (AE_BAD_PARAMETER);
704     }
705
706     /*
707      * We only care about regions.and objects
708      * that are allowed to have address space handlers
709      */
710     if ((Node->Type != ACPI_TYPE_DEVICE) &&
711         (Node->Type != ACPI_TYPE_REGION) &&
712         (Node != AcpiGbl_RootNode))
713     {
714         return (AE_OK);
715     }
716
717     /* Check for an existing internal object */
718
719     ObjDesc = AcpiNsGetAttachedObject (Node);
720     if (!ObjDesc)
721     {
722         /* No object, just exit */
723
724         return (AE_OK);
725     }
726
727     /* Devices are handled different than regions */
728
729     if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_DEVICE)
730     {
731         /* Check if this Device already has a handler for this address space */
732
733         NextHandlerObj = ObjDesc->Device.Handler;
734         while (NextHandlerObj)
735         {
736             /* Found a handler, is it for the same address space? */
737
738             if (NextHandlerObj->AddressSpace.SpaceId == HandlerObj->AddressSpace.SpaceId)
739             {
740                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
741                     "Found handler for region [%s] in device %p(%p) handler %p\n",
742                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
743                     ObjDesc, NextHandlerObj, HandlerObj));
744
745                 /*
746                  * Since the object we found it on was a device, then it
747                  * means that someone has already installed a handler for
748                  * the branch of the namespace from this device on.  Just
749                  * bail out telling the walk routine to not traverse this
750                  * branch.  This preserves the scoping rule for handlers.
751                  */
752                 return (AE_CTRL_DEPTH);
753             }
754
755             /* Walk the linked list of handlers attached to this device */
756
757             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
758         }
759
760         /*
761          * As long as the device didn't have a handler for this
762          * space we don't care about it.  We just ignore it and
763          * proceed.
764          */
765         return (AE_OK);
766     }
767
768     /* Object is a Region */
769
770     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
771     {
772         /*
773          * This region is for a different address space
774          * -- just ignore it
775          */
776         return (AE_OK);
777     }
778
779     /*
780      * Now we have a region and it is for the handler's address
781      * space type.
782      *
783      * First disconnect region for any previous handler (if any)
784      */
785     AcpiEvDetachRegion (ObjDesc, FALSE);
786
787     /* Connect the region to the new handler */
788
789     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
790     return (Status);
791 }
792
793 /*******************************************************************************
794  *
795  * FUNCTION:    AcpiEvRegRun
796  *
797  * PARAMETERS:  WalkNamespace callback
798  *
799  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
800  *
801  ******************************************************************************/
802
803 ACPI_STATUS
804 AcpiEvRegRun (
805     ACPI_HANDLE             ObjHandle,
806     UINT32                  Level,
807     void                    *Context,
808     void                    **ReturnValue)
809 {
810     ACPI_OPERAND_OBJECT     *HandlerObj;
811     ACPI_OPERAND_OBJECT     *ObjDesc;
812     ACPI_NAMESPACE_NODE     *Node;
813     ACPI_STATUS             Status;
814
815
816     ACPI_FUNCTION_NAME ("EvRegRun");
817
818
819     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
820
821     /* Parameter validation */
822
823     if (!HandlerObj)
824     {
825         return (AE_OK);
826     }
827
828     /* Convert and validate the device handle */
829
830     Node = AcpiNsMapHandleToNode (ObjHandle);
831     if (!Node)
832     {
833         return (AE_BAD_PARAMETER);
834     }
835
836     /*
837      * We only care about regions.and objects
838      * that are allowed to have address space handlers
839      */
840     if ((Node->Type != ACPI_TYPE_REGION) &&
841         (Node != AcpiGbl_RootNode))
842     {
843         return (AE_OK);
844     }
845
846     /* Check for an existing internal object */
847
848     ObjDesc = AcpiNsGetAttachedObject (Node);
849     if (!ObjDesc)
850     {
851         /* No object, just exit */
852
853         return (AE_OK);
854     }
855
856
857     /* Object is a Region */
858
859     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
860     {
861         /*
862          * This region is for a different address space
863          * -- just ignore it
864          */
865         return (AE_OK);
866     }
867
868     Status = AcpiEvExecuteRegMethod (ObjDesc, 1);
869     return (Status);
870 }
871