Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/******************************************************************************
2
 *
3
 * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
 
117
#define __EVREGION_C__
118
 
119
#include "acpi.h"
120
#include "accommon.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
 
129
/* Local prototypes */
130
 
131
static BOOLEAN
132
AcpiEvHasDefaultHandler (
133
    ACPI_NAMESPACE_NODE     *Node,
134
    ACPI_ADR_SPACE_TYPE     SpaceId);
135
 
2216 Serge 136
static void
137
AcpiEvOrphanEcRegMethod (
138
    void);
139
 
1498 serge 140
static ACPI_STATUS
141
AcpiEvRegRun (
142
    ACPI_HANDLE             ObjHandle,
143
    UINT32                  Level,
144
    void                    *Context,
145
    void                    **ReturnValue);
146
 
147
static ACPI_STATUS
148
AcpiEvInstallHandler (
149
    ACPI_HANDLE             ObjHandle,
150
    UINT32                  Level,
151
    void                    *Context,
152
    void                    **ReturnValue);
153
 
154
/* These are the address spaces that will get default handlers */
155
 
156
#define ACPI_NUM_DEFAULT_SPACES     4
157
 
158
static UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
159
{
160
    ACPI_ADR_SPACE_SYSTEM_MEMORY,
161
    ACPI_ADR_SPACE_SYSTEM_IO,
162
    ACPI_ADR_SPACE_PCI_CONFIG,
163
    ACPI_ADR_SPACE_DATA_TABLE
164
};
165
 
166
 
167
/*******************************************************************************
168
 *
169
 * FUNCTION:    AcpiEvInstallRegionHandlers
170
 *
171
 * PARAMETERS:  None
172
 *
173
 * RETURN:      Status
174
 *
175
 * DESCRIPTION: Installs the core subsystem default address space handlers.
176
 *
177
 ******************************************************************************/
178
 
179
ACPI_STATUS
180
AcpiEvInstallRegionHandlers (
181
    void)
182
{
183
    ACPI_STATUS             Status;
184
    UINT32                  i;
185
 
186
 
187
    ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
188
 
189
 
190
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
191
    if (ACPI_FAILURE (Status))
192
    {
193
        return_ACPI_STATUS (Status);
194
    }
195
 
196
    /*
197
     * All address spaces (PCI Config, EC, SMBus) are scope dependent and
198
     * registration must occur for a specific device.
199
     *
200
     * In the case of the system memory and IO address spaces there is
201
     * currently no device associated with the address space. For these we
202
     * use the root.
203
     *
204
     * We install the default PCI config space handler at the root so that
205
     * this space is immediately available even though the we have not
206
     * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
207
     * specification which states that the PCI config space must be always
208
     * available -- even though we are nowhere near ready to find the PCI root
209
     * buses at this point.
210
     *
211
     * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
212
     * has already been installed (via AcpiInstallAddressSpaceHandler).
213
     * Similar for AE_SAME_HANDLER.
214
     */
215
    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
216
    {
217
        Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
218
                    AcpiGbl_DefaultAddressSpaces[i],
219
                    ACPI_DEFAULT_HANDLER, NULL, NULL);
220
        switch (Status)
221
        {
222
        case AE_OK:
223
        case AE_SAME_HANDLER:
224
        case AE_ALREADY_EXISTS:
225
 
226
            /* These exceptions are all OK */
227
 
228
            Status = AE_OK;
229
            break;
230
 
231
        default:
232
 
233
            goto UnlockAndExit;
234
        }
235
    }
236
 
237
UnlockAndExit:
238
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
239
    return_ACPI_STATUS (Status);
240
}
241
 
242
 
243
/*******************************************************************************
244
 *
245
 * FUNCTION:    AcpiEvHasDefaultHandler
246
 *
247
 * PARAMETERS:  Node                - Namespace node for the device
248
 *              SpaceId             - The address space ID
249
 *
250
 * RETURN:      TRUE if default handler is installed, FALSE otherwise
251
 *
252
 * DESCRIPTION: Check if the default handler is installed for the requested
253
 *              space ID.
254
 *
255
 ******************************************************************************/
256
 
257
static BOOLEAN
258
AcpiEvHasDefaultHandler (
259
    ACPI_NAMESPACE_NODE     *Node,
260
    ACPI_ADR_SPACE_TYPE     SpaceId)
261
{
262
    ACPI_OPERAND_OBJECT     *ObjDesc;
263
    ACPI_OPERAND_OBJECT     *HandlerObj;
264
 
265
 
266
    /* Must have an existing internal object */
267
 
268
    ObjDesc = AcpiNsGetAttachedObject (Node);
269
    if (ObjDesc)
270
    {
271
        HandlerObj = ObjDesc->Device.Handler;
272
 
273
        /* Walk the linked list of handlers for this object */
274
 
275
        while (HandlerObj)
276
        {
277
            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
278
            {
279
                if (HandlerObj->AddressSpace.HandlerFlags &
280
                        ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
281
                {
282
                    return (TRUE);
283
                }
284
            }
285
 
286
            HandlerObj = HandlerObj->AddressSpace.Next;
287
        }
288
    }
289
 
290
    return (FALSE);
291
}
292
 
293
 
294
/*******************************************************************************
295
 *
296
 * FUNCTION:    AcpiEvInitializeOpRegions
297
 *
298
 * PARAMETERS:  None
299
 *
300
 * RETURN:      Status
301
 *
302
 * DESCRIPTION: Execute _REG methods for all Operation Regions that have
303
 *              an installed default region handler.
304
 *
305
 ******************************************************************************/
306
 
307
ACPI_STATUS
308
AcpiEvInitializeOpRegions (
309
    void)
310
{
311
    ACPI_STATUS             Status;
312
    UINT32                  i;
313
 
314
 
315
    ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
316
 
317
 
318
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
319
    if (ACPI_FAILURE (Status))
320
    {
321
        return_ACPI_STATUS (Status);
322
    }
323
 
324
    /* Run the _REG methods for OpRegions in each default address space */
325
 
326
    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
327
    {
328
        /*
329
         * Make sure the installed handler is the DEFAULT handler. If not the
330
         * default, the _REG methods will have already been run (when the
331
         * handler was installed)
332
         */
333
        if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
334
               AcpiGbl_DefaultAddressSpaces[i]))
335
        {
336
            Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
337
                        AcpiGbl_DefaultAddressSpaces[i]);
338
        }
339
    }
340
 
2216 Serge 341
    AcpiGbl_RegMethodsExecuted = TRUE;
342
 
1498 serge 343
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
344
    return_ACPI_STATUS (Status);
345
}
346
 
347
 
348
/*******************************************************************************
349
 *
350
 * FUNCTION:    AcpiEvExecuteRegMethod
351
 *
352
 * PARAMETERS:  RegionObj           - Region object
353
 *              Function            - Passed to _REG: On (1) or Off (0)
354
 *
355
 * RETURN:      Status
356
 *
357
 * DESCRIPTION: Execute _REG method for a region
358
 *
359
 ******************************************************************************/
360
 
361
ACPI_STATUS
362
AcpiEvExecuteRegMethod (
363
    ACPI_OPERAND_OBJECT     *RegionObj,
364
    UINT32                  Function)
365
{
366
    ACPI_EVALUATE_INFO      *Info;
367
    ACPI_OPERAND_OBJECT     *Args[3];
368
    ACPI_OPERAND_OBJECT     *RegionObj2;
369
    ACPI_STATUS             Status;
370
 
371
 
372
    ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
373
 
374
 
375
    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
376
    if (!RegionObj2)
377
    {
378
        return_ACPI_STATUS (AE_NOT_EXIST);
379
    }
380
 
381
    if (RegionObj2->Extra.Method_REG == NULL)
382
    {
383
        return_ACPI_STATUS (AE_OK);
384
    }
385
 
386
    /* Allocate and initialize the evaluation information block */
387
 
388
    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
389
    if (!Info)
390
    {
391
        return_ACPI_STATUS (AE_NO_MEMORY);
392
    }
393
 
394
    Info->PrefixNode = RegionObj2->Extra.Method_REG;
395
    Info->Pathname = NULL;
396
    Info->Parameters = Args;
397
    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
398
 
399
    /*
400
     * The _REG method has two arguments:
401
     *
402
     * Arg0 - Integer:
403
     *  Operation region space ID Same value as RegionObj->Region.SpaceId
404
     *
405
     * Arg1 - Integer:
406
     *  connection status 1 for connecting the handler, 0 for disconnecting
407
     *  the handler (Passed as a parameter)
408
     */
409
    Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
410
    if (!Args[0])
411
    {
412
        Status = AE_NO_MEMORY;
413
        goto Cleanup1;
414
    }
415
 
416
    Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
417
    if (!Args[1])
418
    {
419
        Status = AE_NO_MEMORY;
420
        goto Cleanup2;
421
    }
422
 
423
    Args[2] = NULL; /* Terminate list */
424
 
425
    /* Execute the method, no return value */
426
 
427
    ACPI_DEBUG_EXEC (
428
        AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
429
 
430
    Status = AcpiNsEvaluate (Info);
431
    AcpiUtRemoveReference (Args[1]);
432
 
433
Cleanup2:
434
    AcpiUtRemoveReference (Args[0]);
435
 
436
Cleanup1:
437
    ACPI_FREE (Info);
438
    return_ACPI_STATUS (Status);
439
}
440
 
441
 
442
/*******************************************************************************
443
 *
444
 * FUNCTION:    AcpiEvAddressSpaceDispatch
445
 *
446
 * PARAMETERS:  RegionObj           - Internal region object
447
 *              Function            - Read or Write operation
448
 *              RegionOffset        - Where in the region to read or write
449
 *              BitWidth            - Field width in bits (8, 16, 32, or 64)
450
 *              Value               - Pointer to in or out value, must be
451
 *                                    a full 64-bit integer
452
 *
453
 * RETURN:      Status
454
 *
455
 * DESCRIPTION: Dispatch an address space or operation region access to
456
 *              a previously installed handler.
457
 *
458
 ******************************************************************************/
459
 
460
ACPI_STATUS
461
AcpiEvAddressSpaceDispatch (
462
    ACPI_OPERAND_OBJECT     *RegionObj,
463
    UINT32                  Function,
464
    UINT32                  RegionOffset,
465
    UINT32                  BitWidth,
466
    UINT64                  *Value)
467
{
468
    ACPI_STATUS             Status;
469
    ACPI_ADR_SPACE_HANDLER  Handler;
470
    ACPI_ADR_SPACE_SETUP    RegionSetup;
471
    ACPI_OPERAND_OBJECT     *HandlerDesc;
472
    ACPI_OPERAND_OBJECT     *RegionObj2;
473
    void                    *RegionContext = NULL;
474
 
475
 
476
    ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
477
 
478
 
479
    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
480
    if (!RegionObj2)
481
    {
482
        return_ACPI_STATUS (AE_NOT_EXIST);
483
    }
484
 
485
    /* Ensure that there is a handler associated with this region */
486
 
487
    HandlerDesc = RegionObj->Region.Handler;
488
    if (!HandlerDesc)
489
    {
490
        ACPI_ERROR ((AE_INFO,
491
            "No handler for Region [%4.4s] (%p) [%s]",
492
            AcpiUtGetNodeName (RegionObj->Region.Node),
493
            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
494
 
495
        return_ACPI_STATUS (AE_NOT_EXIST);
496
    }
497
 
498
    /*
499
     * It may be the case that the region has never been initialized.
500
     * Some types of regions require special init code
501
     */
502
    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
503
    {
504
        /* This region has not been initialized yet, do it */
505
 
506
        RegionSetup = HandlerDesc->AddressSpace.Setup;
507
        if (!RegionSetup)
508
        {
509
            /* No initialization routine, exit with error */
510
 
511
            ACPI_ERROR ((AE_INFO,
512
                "No init routine for region(%p) [%s]",
513
                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
514
            return_ACPI_STATUS (AE_NOT_EXIST);
515
        }
516
 
517
        /*
518
         * We must exit the interpreter because the region setup will
519
         * potentially execute control methods (for example, the _REG method
520
         * for this region)
521
         */
522
        AcpiExExitInterpreter ();
523
 
524
        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
525
                    HandlerDesc->AddressSpace.Context, &RegionContext);
526
 
527
        /* Re-enter the interpreter */
528
 
529
        AcpiExEnterInterpreter ();
530
 
531
        /* Check for failure of the Region Setup */
532
 
533
        if (ACPI_FAILURE (Status))
534
        {
535
            ACPI_EXCEPTION ((AE_INFO, Status,
536
                "During region initialization: [%s]",
537
                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
538
            return_ACPI_STATUS (Status);
539
        }
540
 
541
        /* Region initialization may have been completed by RegionSetup */
542
 
543
        if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
544
        {
545
            RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
546
 
547
            if (RegionObj2->Extra.RegionContext)
548
            {
549
                /* The handler for this region was already installed */
550
 
551
                ACPI_FREE (RegionContext);
552
            }
553
            else
554
            {
555
                /*
556
                 * Save the returned context for use in all accesses to
557
                 * this particular region
558
                 */
559
                RegionObj2->Extra.RegionContext = RegionContext;
560
            }
561
        }
562
    }
563
 
564
    /* We have everything we need, we can invoke the address space handler */
565
 
566
    Handler = HandlerDesc->AddressSpace.Handler;
567
 
568
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
569
        "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
570
        &RegionObj->Region.Handler->AddressSpace, Handler,
571
        ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
572
        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
573
 
574
    if (!(HandlerDesc->AddressSpace.HandlerFlags &
575
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
576
    {
577
        /*
578
         * For handlers other than the default (supplied) handlers, we must
579
         * exit the interpreter because the handler *might* block -- we don't
580
         * know what it will do, so we can't hold the lock on the intepreter.
581
         */
582
        AcpiExExitInterpreter();
583
    }
584
 
585
    /* Call the handler */
586
 
587
    Status = Handler (Function,
588
        (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
589
        HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
590
 
591
    if (ACPI_FAILURE (Status))
592
    {
593
        ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
594
            AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
595
    }
596
 
597
    if (!(HandlerDesc->AddressSpace.HandlerFlags &
598
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
599
    {
600
        /*
601
         * We just returned from a non-default handler, we must re-enter the
602
         * interpreter
603
         */
604
       AcpiExEnterInterpreter ();
605
    }
606
 
607
    return_ACPI_STATUS (Status);
608
}
609
 
610
 
611
/*******************************************************************************
612
 *
613
 * FUNCTION:    AcpiEvDetachRegion
614
 *
615
 * PARAMETERS:  RegionObj           - Region Object
616
 *              AcpiNsIsLocked      - Namespace Region Already Locked?
617
 *
618
 * RETURN:      None
619
 *
620
 * DESCRIPTION: Break the association between the handler and the region
621
 *              this is a two way association.
622
 *
623
 ******************************************************************************/
624
 
625
void
626
AcpiEvDetachRegion(
627
    ACPI_OPERAND_OBJECT     *RegionObj,
628
    BOOLEAN                 AcpiNsIsLocked)
629
{
630
    ACPI_OPERAND_OBJECT     *HandlerObj;
631
    ACPI_OPERAND_OBJECT     *ObjDesc;
632
    ACPI_OPERAND_OBJECT     **LastObjPtr;
633
    ACPI_ADR_SPACE_SETUP    RegionSetup;
634
    void                    **RegionContext;
635
    ACPI_OPERAND_OBJECT     *RegionObj2;
636
    ACPI_STATUS             Status;
637
 
638
 
639
    ACPI_FUNCTION_TRACE (EvDetachRegion);
640
 
641
 
642
    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
643
    if (!RegionObj2)
644
    {
645
        return_VOID;
646
    }
647
    RegionContext = &RegionObj2->Extra.RegionContext;
648
 
649
    /* Get the address handler from the region object */
650
 
651
    HandlerObj = RegionObj->Region.Handler;
652
    if (!HandlerObj)
653
    {
654
        /* This region has no handler, all done */
655
 
656
        return_VOID;
657
    }
658
 
659
    /* Find this region in the handler's list */
660
 
661
    ObjDesc = HandlerObj->AddressSpace.RegionList;
662
    LastObjPtr = &HandlerObj->AddressSpace.RegionList;
663
 
664
    while (ObjDesc)
665
    {
666
        /* Is this the correct Region? */
667
 
668
        if (ObjDesc == RegionObj)
669
        {
670
            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
671
                "Removing Region %p from address handler %p\n",
672
                RegionObj, HandlerObj));
673
 
674
            /* This is it, remove it from the handler's list */
675
 
676
            *LastObjPtr = ObjDesc->Region.Next;
677
            ObjDesc->Region.Next = NULL;        /* Must clear field */
678
 
679
            if (AcpiNsIsLocked)
680
            {
681
                Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
682
                if (ACPI_FAILURE (Status))
683
                {
684
                    return_VOID;
685
                }
686
            }
687
 
688
            /* Now stop region accesses by executing the _REG method */
689
 
2216 Serge 690
            Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
1498 serge 691
            if (ACPI_FAILURE (Status))
692
            {
693
                ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
694
                    AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
695
            }
696
 
697
            if (AcpiNsIsLocked)
698
            {
699
                Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
700
                if (ACPI_FAILURE (Status))
701
                {
702
                    return_VOID;
703
                }
704
            }
705
 
706
            /*
707
             * If the region has been activated, call the setup handler with
708
             * the deactivate notification
709
             */
710
            if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
711
            {
712
                RegionSetup = HandlerObj->AddressSpace.Setup;
713
                Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
714
                    HandlerObj->AddressSpace.Context, RegionContext);
715
 
716
                /* Init routine may fail, Just ignore errors */
717
 
718
                if (ACPI_FAILURE (Status))
719
                {
720
                    ACPI_EXCEPTION ((AE_INFO, Status,
721
                        "from region handler - deactivate, [%s]",
722
                        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
723
                }
724
 
725
                RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
726
            }
727
 
728
            /*
729
             * Remove handler reference in the region
730
             *
731
             * NOTE: this doesn't mean that the region goes away, the region
732
             * is just inaccessible as indicated to the _REG method
733
             *
734
             * If the region is on the handler's list, this must be the
735
             * region's handler
736
             */
737
            RegionObj->Region.Handler = NULL;
738
            AcpiUtRemoveReference (HandlerObj);
739
 
740
            return_VOID;
741
        }
742
 
743
        /* Walk the linked list of handlers */
744
 
745
        LastObjPtr = &ObjDesc->Region.Next;
746
        ObjDesc = ObjDesc->Region.Next;
747
    }
748
 
749
    /* If we get here, the region was not in the handler's region list */
750
 
751
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
752
        "Cannot remove region %p from address handler %p\n",
753
        RegionObj, HandlerObj));
754
 
755
    return_VOID;
756
}
757
 
758
 
759
/*******************************************************************************
760
 *
761
 * FUNCTION:    AcpiEvAttachRegion
762
 *
763
 * PARAMETERS:  HandlerObj          - Handler Object
764
 *              RegionObj           - Region Object
765
 *              AcpiNsIsLocked      - Namespace Region Already Locked?
766
 *
767
 * RETURN:      None
768
 *
769
 * DESCRIPTION: Create the association between the handler and the region
770
 *              this is a two way association.
771
 *
772
 ******************************************************************************/
773
 
774
ACPI_STATUS
775
AcpiEvAttachRegion (
776
    ACPI_OPERAND_OBJECT     *HandlerObj,
777
    ACPI_OPERAND_OBJECT     *RegionObj,
778
    BOOLEAN                 AcpiNsIsLocked)
779
{
780
 
781
    ACPI_FUNCTION_TRACE (EvAttachRegion);
782
 
783
 
784
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
785
        "Adding Region [%4.4s] %p to address handler %p [%s]\n",
786
        AcpiUtGetNodeName (RegionObj->Region.Node),
787
        RegionObj, HandlerObj,
788
        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
789
 
790
    /* Link this region to the front of the handler's list */
791
 
792
    RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
793
    HandlerObj->AddressSpace.RegionList = RegionObj;
794
 
795
    /* Install the region's handler */
796
 
797
    if (RegionObj->Region.Handler)
798
    {
799
        return_ACPI_STATUS (AE_ALREADY_EXISTS);
800
    }
801
 
802
    RegionObj->Region.Handler = HandlerObj;
803
    AcpiUtAddReference (HandlerObj);
804
 
805
    return_ACPI_STATUS (AE_OK);
806
}
807
 
808
 
809
/*******************************************************************************
810
 *
811
 * FUNCTION:    AcpiEvInstallHandler
812
 *
813
 * PARAMETERS:  WalkNamespace callback
814
 *
815
 * DESCRIPTION: This routine installs an address handler into objects that are
816
 *              of type Region or Device.
817
 *
818
 *              If the Object is a Device, and the device has a handler of
819
 *              the same type then the search is terminated in that branch.
820
 *
821
 *              This is because the existing handler is closer in proximity
822
 *              to any more regions than the one we are trying to install.
823
 *
824
 ******************************************************************************/
825
 
826
static ACPI_STATUS
827
AcpiEvInstallHandler (
828
    ACPI_HANDLE             ObjHandle,
829
    UINT32                  Level,
830
    void                    *Context,
831
    void                    **ReturnValue)
832
{
833
    ACPI_OPERAND_OBJECT     *HandlerObj;
834
    ACPI_OPERAND_OBJECT     *NextHandlerObj;
835
    ACPI_OPERAND_OBJECT     *ObjDesc;
836
    ACPI_NAMESPACE_NODE     *Node;
837
    ACPI_STATUS             Status;
838
 
839
 
840
    ACPI_FUNCTION_NAME (EvInstallHandler);
841
 
842
 
843
    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
844
 
845
    /* Parameter validation */
846
 
847
    if (!HandlerObj)
848
    {
849
        return (AE_OK);
850
    }
851
 
852
    /* Convert and validate the device handle */
853
 
854
    Node = AcpiNsValidateHandle (ObjHandle);
855
    if (!Node)
856
    {
857
        return (AE_BAD_PARAMETER);
858
    }
859
 
860
    /*
861
     * We only care about regions and objects that are allowed to have
862
     * address space handlers
863
     */
864
    if ((Node->Type != ACPI_TYPE_DEVICE) &&
865
        (Node->Type != ACPI_TYPE_REGION) &&
866
        (Node != AcpiGbl_RootNode))
867
    {
868
        return (AE_OK);
869
    }
870
 
871
    /* Check for an existing internal object */
872
 
873
    ObjDesc = AcpiNsGetAttachedObject (Node);
874
    if (!ObjDesc)
875
    {
876
        /* No object, just exit */
877
 
878
        return (AE_OK);
879
    }
880
 
881
    /* Devices are handled different than regions */
882
 
883
    if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
884
    {
885
        /* Check if this Device already has a handler for this address space */
886
 
887
        NextHandlerObj = ObjDesc->Device.Handler;
888
        while (NextHandlerObj)
889
        {
890
            /* Found a handler, is it for the same address space? */
891
 
892
            if (NextHandlerObj->AddressSpace.SpaceId ==
893
                    HandlerObj->AddressSpace.SpaceId)
894
            {
895
                ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
896
                    "Found handler for region [%s] in device %p(%p) "
897
                    "handler %p\n",
898
                    AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
899
                    ObjDesc, NextHandlerObj, HandlerObj));
900
 
901
                /*
902
                 * Since the object we found it on was a device, then it
903
                 * means that someone has already installed a handler for
904
                 * the branch of the namespace from this device on. Just
905
                 * bail out telling the walk routine to not traverse this
906
                 * branch. This preserves the scoping rule for handlers.
907
                 */
908
                return (AE_CTRL_DEPTH);
909
            }
910
 
911
            /* Walk the linked list of handlers attached to this device */
912
 
913
            NextHandlerObj = NextHandlerObj->AddressSpace.Next;
914
        }
915
 
916
        /*
917
         * As long as the device didn't have a handler for this space we
918
         * don't care about it. We just ignore it and proceed.
919
         */
920
        return (AE_OK);
921
    }
922
 
923
    /* Object is a Region */
924
 
925
    if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
926
    {
927
        /* This region is for a different address space, just ignore it */
928
 
929
        return (AE_OK);
930
    }
931
 
932
    /*
933
     * Now we have a region and it is for the handler's address space type.
934
     *
935
     * First disconnect region for any previous handler (if any)
936
     */
937
    AcpiEvDetachRegion (ObjDesc, FALSE);
938
 
939
    /* Connect the region to the new handler */
940
 
941
    Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
942
    return (Status);
943
}
944
 
945
 
946
/*******************************************************************************
947
 *
948
 * FUNCTION:    AcpiEvInstallSpaceHandler
949
 *
950
 * PARAMETERS:  Node            - Namespace node for the device
951
 *              SpaceId         - The address space ID
952
 *              Handler         - Address of the handler
953
 *              Setup           - Address of the setup function
954
 *              Context         - Value passed to the handler on each access
955
 *
956
 * RETURN:      Status
957
 *
958
 * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
959
 *              Assumes namespace is locked
960
 *
961
 ******************************************************************************/
962
 
963
ACPI_STATUS
964
AcpiEvInstallSpaceHandler (
965
    ACPI_NAMESPACE_NODE     *Node,
966
    ACPI_ADR_SPACE_TYPE     SpaceId,
967
    ACPI_ADR_SPACE_HANDLER  Handler,
968
    ACPI_ADR_SPACE_SETUP    Setup,
969
    void                    *Context)
970
{
971
    ACPI_OPERAND_OBJECT     *ObjDesc;
972
    ACPI_OPERAND_OBJECT     *HandlerObj;
973
    ACPI_STATUS             Status;
974
    ACPI_OBJECT_TYPE        Type;
975
    UINT8                  Flags = 0;
976
 
977
 
978
    ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
979
 
980
 
981
    /*
982
     * This registration is valid for only the types below and the root. This
983
     * is where the default handlers get placed.
984
     */
985
    if ((Node->Type != ACPI_TYPE_DEVICE)     &&
986
        (Node->Type != ACPI_TYPE_PROCESSOR)  &&
987
        (Node->Type != ACPI_TYPE_THERMAL)    &&
988
        (Node != AcpiGbl_RootNode))
989
    {
990
        Status = AE_BAD_PARAMETER;
991
        goto UnlockAndExit;
992
    }
993
 
994
    if (Handler == ACPI_DEFAULT_HANDLER)
995
    {
996
        Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
997
 
998
        switch (SpaceId)
999
        {
1000
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1001
            Handler = AcpiExSystemMemorySpaceHandler;
1002
            Setup   = AcpiEvSystemMemoryRegionSetup;
1003
            break;
1004
 
1005
        case ACPI_ADR_SPACE_SYSTEM_IO:
1006
            Handler = AcpiExSystemIoSpaceHandler;
1007
            Setup   = AcpiEvIoSpaceRegionSetup;
1008
            break;
1009
 
1010
        case ACPI_ADR_SPACE_PCI_CONFIG:
1011
            Handler = AcpiExPciConfigSpaceHandler;
1012
            Setup   = AcpiEvPciConfigRegionSetup;
1013
            break;
1014
 
1015
        case ACPI_ADR_SPACE_CMOS:
1016
            Handler = AcpiExCmosSpaceHandler;
1017
            Setup   = AcpiEvCmosRegionSetup;
1018
            break;
1019
 
1020
        case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1021
            Handler = AcpiExPciBarSpaceHandler;
1022
            Setup   = AcpiEvPciBarRegionSetup;
1023
            break;
1024
 
1025
        case ACPI_ADR_SPACE_DATA_TABLE:
1026
            Handler = AcpiExDataTableSpaceHandler;
1027
            Setup   = NULL;
1028
            break;
1029
 
1030
        default:
1031
            Status = AE_BAD_PARAMETER;
1032
            goto UnlockAndExit;
1033
        }
1034
    }
1035
 
1036
    /* If the caller hasn't specified a setup routine, use the default */
1037
 
1038
    if (!Setup)
1039
    {
1040
        Setup = AcpiEvDefaultRegionSetup;
1041
    }
1042
 
1043
    /* Check for an existing internal object */
1044
 
1045
    ObjDesc = AcpiNsGetAttachedObject (Node);
1046
    if (ObjDesc)
1047
    {
1048
        /*
1049
         * The attached device object already exists. Make sure the handler
1050
         * is not already installed.
1051
         */
1052
        HandlerObj = ObjDesc->Device.Handler;
1053
 
1054
        /* Walk the handler list for this device */
1055
 
1056
        while (HandlerObj)
1057
        {
1058
            /* Same SpaceId indicates a handler already installed */
1059
 
1060
            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
1061
            {
1062
                if (HandlerObj->AddressSpace.Handler == Handler)
1063
                {
1064
                    /*
1065
                     * It is (relatively) OK to attempt to install the SAME
1066
                     * handler twice. This can easily happen with the
1067
                     * PCI_Config space.
1068
                     */
1069
                    Status = AE_SAME_HANDLER;
1070
                    goto UnlockAndExit;
1071
                }
1072
                else
1073
                {
1074
                    /* A handler is already installed */
1075
 
1076
                    Status = AE_ALREADY_EXISTS;
1077
                }
1078
                goto UnlockAndExit;
1079
            }
1080
 
1081
            /* Walk the linked list of handlers */
1082
 
1083
            HandlerObj = HandlerObj->AddressSpace.Next;
1084
        }
1085
    }
1086
    else
1087
    {
1088
        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1089
            "Creating object on Device %p while installing handler\n", Node));
1090
 
1091
        /* ObjDesc does not exist, create one */
1092
 
1093
        if (Node->Type == ACPI_TYPE_ANY)
1094
        {
1095
            Type = ACPI_TYPE_DEVICE;
1096
        }
1097
        else
1098
        {
1099
            Type = Node->Type;
1100
        }
1101
 
1102
        ObjDesc = AcpiUtCreateInternalObject (Type);
1103
        if (!ObjDesc)
1104
        {
1105
            Status = AE_NO_MEMORY;
1106
            goto UnlockAndExit;
1107
        }
1108
 
1109
        /* Init new descriptor */
1110
 
1111
        ObjDesc->Common.Type = (UINT8) Type;
1112
 
1113
        /* Attach the new object to the Node */
1114
 
1115
        Status = AcpiNsAttachObject (Node, ObjDesc, Type);
1116
 
1117
        /* Remove local reference to the object */
1118
 
1119
        AcpiUtRemoveReference (ObjDesc);
1120
 
1121
        if (ACPI_FAILURE (Status))
1122
        {
1123
            goto UnlockAndExit;
1124
        }
1125
    }
1126
 
1127
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1128
        "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
1129
        AcpiUtGetRegionName (SpaceId), SpaceId,
1130
        AcpiUtGetNodeName (Node), Node, ObjDesc));
1131
 
1132
    /*
1133
     * Install the handler
1134
     *
1135
     * At this point there is no existing handler. Just allocate the object
1136
     * for the handler and link it into the list.
1137
     */
1138
    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
1139
    if (!HandlerObj)
1140
    {
1141
        Status = AE_NO_MEMORY;
1142
        goto UnlockAndExit;
1143
    }
1144
 
1145
    /* Init handler obj */
1146
 
1147
    HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
1148
    HandlerObj->AddressSpace.HandlerFlags = Flags;
1149
    HandlerObj->AddressSpace.RegionList = NULL;
1150
    HandlerObj->AddressSpace.Node = Node;
1151
    HandlerObj->AddressSpace.Handler = Handler;
1152
    HandlerObj->AddressSpace.Context = Context;
1153
    HandlerObj->AddressSpace.Setup  = Setup;
1154
 
1155
    /* Install at head of Device.AddressSpace list */
1156
 
1157
    HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
1158
 
1159
    /*
1160
     * The Device object is the first reference on the HandlerObj.
1161
     * Each region that uses the handler adds a reference.
1162
     */
1163
    ObjDesc->Device.Handler = HandlerObj;
1164
 
1165
    /*
1166
     * Walk the namespace finding all of the regions this
1167
     * handler will manage.
1168
     *
1169
     * Start at the device and search the branch toward
1170
     * the leaf nodes until either the leaf is encountered or
1171
     * a device is detected that has an address handler of the
1172
     * same type.
1173
     *
1174
     * In either case, back up and search down the remainder
1175
     * of the branch
1176
     */
1177
    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1178
                ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
1179
                HandlerObj, NULL);
1180
 
1181
UnlockAndExit:
1182
    return_ACPI_STATUS (Status);
1183
}
1184
 
1185
 
1186
/*******************************************************************************
1187
 *
1188
 * FUNCTION:    AcpiEvExecuteRegMethods
1189
 *
1190
 * PARAMETERS:  Node            - Namespace node for the device
1191
 *              SpaceId         - The address space ID
1192
 *
1193
 * RETURN:      Status
1194
 *
1195
 * DESCRIPTION: Run all _REG methods for the input Space ID;
1196
 *              Note: assumes namespace is locked, or system init time.
1197
 *
1198
 ******************************************************************************/
1199
 
1200
ACPI_STATUS
1201
AcpiEvExecuteRegMethods (
1202
    ACPI_NAMESPACE_NODE     *Node,
1203
    ACPI_ADR_SPACE_TYPE     SpaceId)
1204
{
1205
    ACPI_STATUS             Status;
1206
 
1207
 
1208
    ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
1209
 
1210
 
1211
    /*
1212
     * Run all _REG methods for all Operation Regions for this space ID. This
1213
     * is a separate walk in order to handle any interdependencies between
1214
     * regions and _REG methods. (i.e. handlers must be installed for all
1215
     * regions of this Space ID before we can run any _REG methods)
1216
     */
1217
    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1218
                ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL,
1219
                &SpaceId, NULL);
1220
 
2216 Serge 1221
    /* Special case for EC: handle "orphan" _REG methods with no region */
1222
 
1223
    if (SpaceId == ACPI_ADR_SPACE_EC)
1224
    {
1225
        AcpiEvOrphanEcRegMethod ();
1226
    }
1227
 
1498 serge 1228
    return_ACPI_STATUS (Status);
1229
}
1230
 
1231
 
1232
/*******************************************************************************
1233
 *
1234
 * FUNCTION:    AcpiEvRegRun
1235
 *
1236
 * PARAMETERS:  WalkNamespace callback
1237
 *
1238
 * DESCRIPTION: Run _REG method for region objects of the requested spaceID
1239
 *
1240
 ******************************************************************************/
1241
 
1242
static ACPI_STATUS
1243
AcpiEvRegRun (
1244
    ACPI_HANDLE             ObjHandle,
1245
    UINT32                  Level,
1246
    void                    *Context,
1247
    void                    **ReturnValue)
1248
{
1249
    ACPI_OPERAND_OBJECT     *ObjDesc;
1250
    ACPI_NAMESPACE_NODE     *Node;
1251
    ACPI_ADR_SPACE_TYPE     SpaceId;
1252
    ACPI_STATUS             Status;
1253
 
1254
 
1255
    SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
1256
 
1257
    /* Convert and validate the device handle */
1258
 
1259
    Node = AcpiNsValidateHandle (ObjHandle);
1260
    if (!Node)
1261
    {
1262
        return (AE_BAD_PARAMETER);
1263
    }
1264
 
1265
    /*
1266
     * We only care about regions.and objects that are allowed to have address
1267
     * space handlers
1268
     */
1269
    if ((Node->Type != ACPI_TYPE_REGION) &&
1270
        (Node != AcpiGbl_RootNode))
1271
    {
1272
        return (AE_OK);
1273
    }
1274
 
1275
    /* Check for an existing internal object */
1276
 
1277
    ObjDesc = AcpiNsGetAttachedObject (Node);
1278
    if (!ObjDesc)
1279
    {
1280
        /* No object, just exit */
1281
 
1282
        return (AE_OK);
1283
    }
1284
 
1285
    /* Object is a Region */
1286
 
1287
    if (ObjDesc->Region.SpaceId != SpaceId)
1288
    {
1289
        /* This region is for a different address space, just ignore it */
1290
 
1291
        return (AE_OK);
1292
    }
1293
 
2216 Serge 1294
    Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT);
1498 serge 1295
    return (Status);
1296
}
1297
 
2216 Serge 1298
 
1299
/*******************************************************************************
1300
 *
1301
 * FUNCTION:    AcpiEvOrphanEcRegMethod
1302
 *
1303
 * PARAMETERS:  None
1304
 *
1305
 * RETURN:      None
1306
 *
1307
 * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
1308
 *              device. This is a _REG method that has no corresponding region
1309
 *              within the EC device scope. The orphan _REG method appears to
1310
 *              have been enabled by the description of the ECDT in the ACPI
1311
 *              specification: "The availability of the region space can be
1312
 *              detected by providing a _REG method object underneath the
1313
 *              Embedded Controller device."
1314
 *
1315
 *              To quickly access the EC device, we use the EC_ID that appears
1316
 *              within the ECDT. Otherwise, we would need to perform a time-
1317
 *              consuming namespace walk, executing _HID methods to find the
1318
 *              EC device.
1319
 *
1320
 ******************************************************************************/
1321
 
1322
static void
1323
AcpiEvOrphanEcRegMethod (
1324
    void)
1325
{
1326
    ACPI_TABLE_ECDT         *Table;
1327
    ACPI_STATUS             Status;
1328
    ACPI_OBJECT_LIST        Args;
1329
    ACPI_OBJECT             Objects[2];
1330
    ACPI_NAMESPACE_NODE     *EcDeviceNode;
1331
    ACPI_NAMESPACE_NODE     *RegMethod;
1332
    ACPI_NAMESPACE_NODE     *NextNode;
1333
 
1334
 
1335
    ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);
1336
 
1337
 
1338
    /* Get the ECDT (if present in system) */
1339
 
1340
    Status = AcpiGetTable (ACPI_SIG_ECDT, 0,
1341
        ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Table));
1342
    if (ACPI_FAILURE (Status))
1343
    {
1344
        return_VOID;
1345
    }
1346
 
1347
    /* We need a valid EC_ID string */
1348
 
1349
    if (!(*Table->Id))
1350
    {
1351
        return_VOID;
1352
    }
1353
 
1354
    /* Namespace is currently locked, must release */
1355
 
1356
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1357
 
1358
    /* Get a handle to the EC device referenced in the ECDT */
1359
 
1360
    Status = AcpiGetHandle (NULL,
1361
        ACPI_CAST_PTR (char, Table->Id),
1362
        ACPI_CAST_PTR (ACPI_HANDLE, &EcDeviceNode));
1363
    if (ACPI_FAILURE (Status))
1364
    {
1365
        goto Exit;
1366
    }
1367
 
1368
    /* Get a handle to a _REG method immediately under the EC device */
1369
 
1370
    Status = AcpiGetHandle (EcDeviceNode,
1371
        METHOD_NAME__REG, ACPI_CAST_PTR (ACPI_HANDLE, &RegMethod));
1372
    if (ACPI_FAILURE (Status))
1373
    {
1374
        goto Exit;
1375
    }
1376
 
1377
    /*
1378
     * Execute the _REG method only if there is no Operation Region in
1379
     * this scope with the Embedded Controller space ID. Otherwise, it
1380
     * will already have been executed. Note, this allows for Regions
1381
     * with other space IDs to be present; but the code below will then
1382
     * execute the _REG method with the EC space ID argument.
1383
     */
1384
    NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
1385
    while (NextNode)
1386
    {
1387
        if ((NextNode->Type == ACPI_TYPE_REGION) &&
1388
            (NextNode->Object) &&
1389
            (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
1390
        {
1391
            goto Exit; /* Do not execute _REG */
1392
        }
1393
        NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
1394
    }
1395
 
1396
    /* Evaluate the _REG(EC,Connect) method */
1397
 
1398
    Args.Count = 2;
1399
    Args.Pointer = Objects;
1400
    Objects[0].Type = ACPI_TYPE_INTEGER;
1401
    Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
1402
    Objects[1].Type = ACPI_TYPE_INTEGER;
1403
    Objects[1].Integer.Value = ACPI_REG_CONNECT;
1404
 
1405
    Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
1406
 
1407
Exit:
1408
    /* We ignore all errors from above, don't care */
1409
 
1410
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1411
    return_VOID;
1412
}