evrgnini.c revision 69450
1/******************************************************************************
2 *
3 * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init
4 *              $Revision: 29 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
13 * 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 __EVRGNINI_C__
119
120#include "acpi.h"
121#include "acevents.h"
122#include "acnamesp.h"
123#include "acinterp.h"
124#include "amlcode.h"
125
126#define _COMPONENT          EVENT_HANDLING
127        MODULE_NAME         ("evrgnini")
128
129
130/*****************************************************************************
131 *
132 * FUNCTION:    AcpiEvSystemMemoryRegionSetup
133 *
134 * PARAMETERS:  RegionObj           - region we are interested in
135 *              Function            - start or stop
136 *              HandlerContext      - Address space handler context
137 *              RegionContext       - Region specific context
138 *
139 * RETURN:      Status
140 *
141 * DESCRIPTION: Do any prep work for region handling, a nop for now
142 *
143 ****************************************************************************/
144
145ACPI_STATUS
146AcpiEvSystemMemoryRegionSetup (
147    ACPI_HANDLE             Handle,
148    UINT32                  Function,
149    void                    *HandlerContext,
150    void                    **RegionContext)
151{
152    FUNCTION_TRACE ("EvSystemMemoryRegionSetup");
153
154
155    if (Function == ACPI_REGION_DEACTIVATE)
156    {
157        if (*RegionContext)
158        {
159            AcpiCmFree (*RegionContext);
160            *RegionContext = NULL;
161        }
162        return_ACPI_STATUS (AE_OK);
163    }
164
165
166    /* Activate.  Create a new context */
167
168    *RegionContext = AcpiCmCallocate (sizeof (MEM_HANDLER_CONTEXT));
169    if (!(*RegionContext))
170    {
171        return_ACPI_STATUS (AE_NO_MEMORY);
172    }
173
174    return_ACPI_STATUS (AE_OK);
175}
176
177
178/*****************************************************************************
179 *
180 * FUNCTION:    AcpiEvIoSpaceRegionSetup
181 *
182 * PARAMETERS:  RegionObj           - region we are interested in
183 *              Function            - start or stop
184 *              HandlerContext      - Address space handler context
185 *              RegionContext       - Region specific context
186 *
187 * RETURN:      Status
188 *
189 * DESCRIPTION: Do any prep work for region handling
190 *
191 ****************************************************************************/
192
193ACPI_STATUS
194AcpiEvIoSpaceRegionSetup (
195    ACPI_HANDLE             Handle,
196    UINT32                  Function,
197    void                    *HandlerContext,
198    void                    **RegionContext)
199{
200    FUNCTION_TRACE ("EvIoSpaceRegionSetup");
201
202    if (Function == ACPI_REGION_DEACTIVATE)
203    {
204        *RegionContext = NULL;
205    }
206    else
207    {
208        *RegionContext = HandlerContext;
209    }
210
211    return_ACPI_STATUS (AE_OK);
212}
213
214
215/*****************************************************************************
216 *
217 * FUNCTION:    AcpiEvPciConfigRegionSetup
218 *
219 * PARAMETERS:  RegionObj           - region we are interested in
220 *              Function            - start or stop
221 *              HandlerContext      - Address space handler context
222 *              RegionContext       - Region specific context
223 *
224 * RETURN:      Status
225 *
226 * DESCRIPTION: Do any prep work for region handling
227 *
228 * MUTEX:       Assumes namespace is not locked
229 *
230 ****************************************************************************/
231
232ACPI_STATUS
233AcpiEvPciConfigRegionSetup (
234    ACPI_HANDLE             Handle,
235    UINT32                  Function,
236    void                    *HandlerContext,
237    void                    **RegionContext)
238{
239    ACPI_STATUS             Status = AE_OK;
240    ACPI_INTEGER            Temp;
241    PCI_HANDLER_CONTEXT     *PciContext = *RegionContext;
242    ACPI_OPERAND_OBJECT     *HandlerObj;
243    ACPI_NAMESPACE_NODE     *Node;
244    ACPI_OPERAND_OBJECT     *RegionObj = (ACPI_OPERAND_OBJECT  *) Handle;
245    DEVICE_ID               ObjectHID;
246
247    FUNCTION_TRACE ("EvPciConfigRegionSetup");
248
249    HandlerObj = RegionObj->Region.AddrHandler;
250
251    if (!HandlerObj)
252    {
253        /*
254         *  No installed handler. This shouldn't happen because the dispatch
255         *  routine checks before we get here, but we check again just in case.
256         */
257        DEBUG_PRINT (TRACE_OPREGION,
258            ("Attempting to init a region 0x%X, with no handler\n", RegionObj));
259        return_ACPI_STATUS(AE_NOT_EXIST);
260    }
261
262    if (Function == ACPI_REGION_DEACTIVATE)
263    {
264        if (PciContext)
265        {
266            AcpiCmFree (PciContext);
267            *RegionContext = NULL;
268        }
269
270        return_ACPI_STATUS (Status);
271    }
272
273
274    /* Create a new context */
275
276    PciContext = AcpiCmCallocate (sizeof(PCI_HANDLER_CONTEXT));
277    if (!PciContext)
278    {
279        return_ACPI_STATUS (AE_NO_MEMORY);
280    }
281
282    /*
283     *  For PCI Config space access, we have to pass the segment, bus,
284     *  device and function numbers.  This routine must acquire those.
285     */
286
287    /*
288     *  First get device and function numbers from the _ADR object
289     *  in the parent's scope.
290     */
291    ACPI_ASSERT(RegionObj->Region.Node);
292
293    Node = AcpiNsGetParentObject (RegionObj->Region.Node);
294
295
296    /* AcpiEvaluate the _ADR object */
297
298    Status = AcpiCmEvaluateNumericObject (METHOD_NAME__ADR, Node, &Temp);
299    /*
300     *  The default is zero, since the allocation above zeroed the data, just
301     *  do nothing on failures.
302     */
303    if (ACPI_SUCCESS (Status))
304    {
305        /*
306         *  Got it..
307         */
308        PciContext->DevFunc = (UINT32) Temp;
309    }
310
311    /*
312     *  Get the _SEG and _BBN values from the device upon which the handler
313     *  is installed.
314     *
315     *  We need to get the _SEG and _BBN objects relative to the PCI BUS device.
316     *  This is the device the handler has been registered to handle.
317     */
318
319    /*
320     *  If the AddrHandler.Node is still pointing to the root, we need
321     *  to scan upward for a PCI Root bridge and re-associate the OpRegion
322     *  handlers with that device.
323     */
324    if (HandlerObj->AddrHandler.Node == AcpiGbl_RootNode)
325    {
326        /*
327         * Node is currently the parent object
328         */
329        while (Node != AcpiGbl_RootNode)
330        {
331            Status = AcpiCmExecute_HID(Node, &ObjectHID);
332
333            if (ACPI_SUCCESS (Status))
334            {
335                if (!(STRNCMP(ObjectHID.Buffer, PCI_ROOT_HID_STRING,
336                                    sizeof (PCI_ROOT_HID_STRING))))
337                {
338                    AcpiInstallAddressSpaceHandler(Node,
339                                        ADDRESS_SPACE_PCI_CONFIG,
340                                        ACPI_DEFAULT_HANDLER, NULL, NULL);
341
342                    break;
343                }
344            }
345
346            Node = AcpiNsGetParentObject(Node);
347        }
348    }
349    else
350    {
351        Node = HandlerObj->AddrHandler.Node;
352    }
353
354    Status = AcpiCmEvaluateNumericObject (METHOD_NAME__SEG, Node, &Temp);
355    if (ACPI_SUCCESS (Status))
356    {
357        /*
358         *  Got it..
359         */
360        PciContext->Seg = (UINT32) Temp;
361    }
362
363    Status = AcpiCmEvaluateNumericObject (METHOD_NAME__BBN, Node, &Temp);
364    if (ACPI_SUCCESS (Status))
365    {
366        /*
367         *  Got it..
368         */
369        PciContext->Bus = (UINT32) Temp;
370    }
371
372    *RegionContext = PciContext;
373
374    return_ACPI_STATUS (AE_OK);
375}
376
377
378/*****************************************************************************
379 *
380 * FUNCTION:    AcpiEvDefaultRegionSetup
381 *
382 * PARAMETERS:  RegionObj           - region we are interested in
383 *              Function            - start or stop
384 *              HandlerContext      - Address space handler context
385 *              RegionContext       - Region specific context
386 *
387 * RETURN:      Status
388 *
389 * DESCRIPTION: Do any prep work for region handling
390 *
391 ****************************************************************************/
392
393ACPI_STATUS
394AcpiEvDefaultRegionSetup (
395    ACPI_HANDLE             Handle,
396    UINT32                  Function,
397    void                    *HandlerContext,
398    void                    **RegionContext)
399{
400    FUNCTION_TRACE ("EvDefaultRegionSetup");
401
402    if (Function == ACPI_REGION_DEACTIVATE)
403    {
404        *RegionContext = NULL;
405    }
406    else
407    {
408        *RegionContext = HandlerContext;
409    }
410
411    return_ACPI_STATUS (AE_OK);
412}
413
414
415/******************************************************************************
416 *
417 * FUNCTION:    AcpiEvInitializeRegion
418 *
419 * PARAMETERS:  RegionObj  - Region we are initializing
420 *
421 * RETURN:      Status
422 *
423 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
424 *              for execution at a later time
425 *
426 *              Get the appropriate address space handler for a newly
427 *              created region.
428 *
429 *              This also performs address space specific intialization.  For
430 *              example, PCI regions must have an _ADR object that contains
431 *              a PCI address in the scope of the defintion.  This address is
432 *              required to perform an access to PCI config space.
433 *
434 ******************************************************************************/
435
436ACPI_STATUS
437AcpiEvInitializeRegion (
438    ACPI_OPERAND_OBJECT     *RegionObj,
439    BOOLEAN                 AcpiNsLocked)
440{
441    ACPI_OPERAND_OBJECT    *HandlerObj;
442    ACPI_OPERAND_OBJECT    *ObjDesc;
443    UINT32                  SpaceId;
444    ACPI_NAMESPACE_NODE    *Node;
445    ACPI_STATUS             Status;
446    ACPI_NAMESPACE_NODE    *MethodNode;
447    ACPI_NAME              *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG;
448
449
450    FUNCTION_TRACE_U32 ("EvInitializeRegion", AcpiNsLocked);
451
452
453    if (!RegionObj)
454    {
455        return_ACPI_STATUS (AE_BAD_PARAMETER);
456    }
457
458    ACPI_ASSERT(RegionObj->Region.Node);
459
460    Node = AcpiNsGetParentObject (RegionObj->Region.Node);
461    SpaceId = RegionObj->Region.SpaceId;
462
463    RegionObj->Region.AddrHandler = NULL;
464    RegionObj->Region.Extra->Extra.Method_REG = NULL;
465    RegionObj->Region.Flags &= ~(AOPOBJ_INITIALIZED);
466
467    /*
468     *  Find any "_REG" associated with this region definition
469     */
470    Status = AcpiNsSearchNode (*RegNamePtr, Node,
471                                   ACPI_TYPE_METHOD, &MethodNode);
472    if (ACPI_SUCCESS (Status))
473    {
474        /*
475         *  The _REG method is optional and there can be only one per region
476         *  definition.  This will be executed when the handler is attached
477         *  or removed
478         */
479        RegionObj->Region.Extra->Extra.Method_REG = MethodNode;
480    }
481
482    /*
483     *  The following loop depends upon the root Node having no parent
484     *  ie: AcpiGbl_RootNode->ParentEntry being set to NULL
485     */
486    while (Node)
487    {
488        /*
489         *  Check to see if a handler exists
490         */
491        HandlerObj = NULL;
492        ObjDesc = AcpiNsGetAttachedObject ((ACPI_HANDLE) Node);
493        if (ObjDesc)
494        {
495            /*
496             *  can only be a handler if the object exists
497             */
498            switch (Node->Type)
499            {
500            case ACPI_TYPE_DEVICE:
501
502                HandlerObj = ObjDesc->Device.AddrHandler;
503                break;
504
505            case ACPI_TYPE_PROCESSOR:
506
507                HandlerObj = ObjDesc->Processor.AddrHandler;
508                break;
509
510            case ACPI_TYPE_THERMAL:
511
512                HandlerObj = ObjDesc->ThermalZone.AddrHandler;
513                break;
514            }
515
516            while (HandlerObj)
517            {
518                /*
519                 *  This guy has at least one address handler
520                 *  see if it has the type we want
521                 */
522                if (HandlerObj->AddrHandler.SpaceId == SpaceId)
523                {
524                    DEBUG_PRINT (TRACE_OPREGION,
525                        ("Found handler (0x%X) for region 0x%X in obj 0x%X\n",
526                        HandlerObj, RegionObj, ObjDesc));
527
528                    /*
529                     *  Found it! Now update the region and the handler
530                     */
531                    AcpiEvAssociateRegionAndHandler (HandlerObj, RegionObj, AcpiNsLocked);
532                    return_ACPI_STATUS (AE_OK);
533                }
534
535                HandlerObj = HandlerObj->AddrHandler.Next;
536
537            } /* while handlerobj */
538        }
539
540        /*
541         *  This one does not have the handler we need
542         *  Pop up one level
543         */
544        Node = AcpiNsGetParentObject (Node);
545
546    } /* while Node != ROOT */
547
548    /*
549     *  If we get here, there is no handler for this region
550     */
551    DEBUG_PRINT (TRACE_OPREGION,
552        ("No handler currently for SpaceId[%d] (Initializing region 0x%X)\n",
553            SpaceId, RegionObj));
554
555    return_ACPI_STATUS (AE_NOT_EXIST);
556}
557
558