Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1498 Rev 2216
Line 6... Line 6...
6
 
6
 
7
/******************************************************************************
7
/******************************************************************************
8
 *
8
 *
9
 * 1. Copyright Notice
9
 * 1. Copyright Notice
10
 *
10
 *
11
 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
12
 * All rights reserved.
12
 * All rights reserved.
13
 *
13
 *
14
 * 2. License
14
 * 2. License
15
 *
15
 *
Line 116... Line 116...
116
 
116
 
117
#include "acpi.h"
117
#include "acpi.h"
118
#include "accommon.h"
118
#include "accommon.h"
119
#include "acevents.h"
119
#include "acevents.h"
120
#include "acnamesp.h"
-
 
Line 121... Line 120...
121
#include "acinterp.h"
120
#include "acnamesp.h"
122
 
121
 
Line -... Line 122...
-
 
122
#define _COMPONENT          ACPI_EVENTS
-
 
123
        ACPI_MODULE_NAME    ("evgpeinit")
-
 
124
 
-
 
125
 
-
 
126
/*
-
 
127
 * Note: History of _PRW support in ACPICA
-
 
128
 *
-
 
129
 * Originally (2000 - 2010), the GPE initialization code performed a walk of
-
 
130
 * the entire namespace to execute the _PRW methods and detect all GPEs
-
 
131
 * capable of waking the system.
-
 
132
 *
-
 
133
 * As of 10/2010, the _PRW method execution has been removed since it is
-
 
134
 * actually unnecessary. The host OS must in fact execute all _PRW methods
-
 
135
 * in order to identify the device/power-resource dependencies. We now put
-
 
136
 * the onus on the host OS to identify the wake GPEs as part of this process
-
 
137
 * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This
-
 
138
 * not only reduces the complexity of the ACPICA initialization code, but in
123
#define _COMPONENT          ACPI_EVENTS
139
 * some cases (on systems with very large namespaces) it should reduce the
124
        ACPI_MODULE_NAME    ("evgpeinit")
140
 * kernel boot time as well.
125
 
141
 */
126
 
142
 
127
/*******************************************************************************
143
/*******************************************************************************
Line 286... Line 302...
286
 *
302
 *
287
 * RETURN:      None
303
 * RETURN:      None
288
 *
304
 *
289
 * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
305
 * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
290
 *              result of a Load() or LoadTable() operation. If new GPE
306
 *              result of a Load() or LoadTable() operation. If new GPE
291
 *              methods have been installed, register the new methods and
307
 *              methods have been installed, register the new methods.
292
 *              enable and runtime GPEs that are associated with them. Also,
-
 
293
 *              run any newly loaded _PRW methods in order to discover any
-
 
294
 *              new CAN_WAKE GPEs.
-
 
295
 *
308
 *
296
 ******************************************************************************/
309
 ******************************************************************************/
Line 297... Line 310...
297
 
310
 
298
void
311
void
Line 301... Line 314...
301
{
314
{
302
    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
315
    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
303
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
316
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
304
    ACPI_GPE_WALK_INFO      WalkInfo;
317
    ACPI_GPE_WALK_INFO      WalkInfo;
305
    ACPI_STATUS             Status = AE_OK;
318
    ACPI_STATUS             Status = AE_OK;
306
    UINT32                  NewWakeGpeCount = 0;
-
 
307
 
-
 
Line 308... Line -...
308
 
-
 
Line 309... Line -...
309
    /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */
-
 
310
 
-
 
311
    WalkInfo.OwnerId = TableOwnerId;
-
 
312
    WalkInfo.ExecuteByOwnerId = TRUE;
-
 
313
    WalkInfo.Count = 0;
-
 
314
 
-
 
315
    if (AcpiGbl_LeaveWakeGpesDisabled)
319
 
316
    {
-
 
317
        /*
-
 
318
         * 1) Run any newly-loaded _PRW methods to find any GPEs that
-
 
319
         * can now be marked as CAN_WAKE GPEs. Note: We must run the
-
 
320
         * _PRW methods before we process the _Lxx/_Exx methods because
320
 
321
         * we will enable all runtime GPEs associated with the new
321
    /*
322
         * _Lxx/_Exx methods at the time we process those methods.
-
 
323
         *
-
 
324
         * Unlock interpreter so that we can run the _PRW methods.
-
 
325
         */
-
 
326
        WalkInfo.GpeBlock = NULL;
-
 
327
        WalkInfo.GpeDevice = NULL;
-
 
328
 
-
 
329
        AcpiExExitInterpreter ();
-
 
330
 
-
 
331
        Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-
 
332
                    ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
-
 
333
                    AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL);
-
 
334
        if (ACPI_FAILURE (Status))
-
 
335
        {
-
 
336
            ACPI_EXCEPTION ((AE_INFO, Status,
-
 
337
                "While executing _PRW methods"));
-
 
338
        }
-
 
339
 
-
 
340
        AcpiExEnterInterpreter ();
-
 
341
        NewWakeGpeCount = WalkInfo.Count;
-
 
342
    }
-
 
343
 
-
 
344
    /*
-
 
345
     * 2) Find any _Lxx/_Exx GPE methods that have just been loaded.
322
     * Find any _Lxx/_Exx GPE methods that have just been loaded.
346
     *
323
     *
347
     * Any GPEs that correspond to new _Lxx/_Exx methods and are not
324
     * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
348
     * marked as CAN_WAKE are immediately enabled.
325
     * enabled.
349
     *
326
     *
350
     * Examine the namespace underneath each GpeDevice within the
327
     * Examine the namespace underneath each GpeDevice within the
351
     * GpeBlock lists.
328
     * GpeBlock lists.
Line 355... Line 332...
355
    {
332
    {
356
        return;
333
        return;
357
    }
334
    }
Line 358... Line 335...
358
 
335
 
-
 
336
    WalkInfo.Count = 0;
359
    WalkInfo.Count = 0;
337
    WalkInfo.OwnerId = TableOwnerId;
Line 360... Line 338...
360
    WalkInfo.EnableThisGpe = TRUE;
338
    WalkInfo.ExecuteByOwnerId = TRUE;
Line 361... Line 339...
361
 
339
 
362
    /* Walk the interrupt level descriptor list */
340
    /* Walk the interrupt level descriptor list */
Line 386... Line 364...
386
        }
364
        }
Line 387... Line 365...
387
 
365
 
388
        GpeXruptInfo = GpeXruptInfo->Next;
366
        GpeXruptInfo = GpeXruptInfo->Next;
Line 389... Line 367...
389
    }
367
    }
390
 
368
 
391
    if (WalkInfo.Count || NewWakeGpeCount)
-
 
392
    {
369
    if (WalkInfo.Count)
393
        ACPI_INFO ((AE_INFO,
-
 
394
            "Enabled %u new runtime GPEs, added %u new wakeup GPEs",
370
    {
Line 395... Line 371...
395
            WalkInfo.Count, NewWakeGpeCount));
371
        ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count));
396
    }
372
    }
397
 
373
 
Line 421... Line 397...
421
 *                  E      - means that the GPE is edge triggered
397
 *                  E      - means that the GPE is edge triggered
422
 *                  xx     - is the GPE number [in HEX]
398
 *                  xx     - is the GPE number [in HEX]
423
 *
399
 *
424
 * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods
400
 * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods
425
 *    with that owner.
401
 * with that owner.
426
 * If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE
-
 
427
 *    method is immediately enabled (Used for Load/LoadTable operators)
-
 
428
 *
402
 *
429
 ******************************************************************************/
403
 ******************************************************************************/
Line 430... Line 404...
430
 
404
 
431
ACPI_STATUS
405
ACPI_STATUS
Line 436... Line 410...
436
    void                    **ReturnValue)
410
    void                    **ReturnValue)
437
{
411
{
438
    ACPI_NAMESPACE_NODE     *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
412
    ACPI_NAMESPACE_NODE     *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
439
    ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
413
    ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
440
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
414
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
441
    ACPI_NAMESPACE_NODE     *GpeDevice;
-
 
442
    ACPI_STATUS             Status;
-
 
443
    UINT32                  GpeNumber;
415
    UINT32                  GpeNumber;
444
    char                    Name[ACPI_NAME_SIZE + 1];
416
    char                    Name[ACPI_NAME_SIZE + 1];
445
    UINT8                   Type;
417
    UINT8                   Type;
Line 472... Line 444...
472
    }
444
    }
Line 473... Line 445...
473
 
445
 
474
    /*
446
    /*
475
     * 3) Edge/Level determination is based on the 2nd character
447
     * 3) Edge/Level determination is based on the 2nd character
476
     *    of the method name
-
 
477
     *
-
 
478
     * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is
-
 
479
     * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set.
448
     *    of the method name
480
     */
449
     */
481
    switch (Name[1])
450
    switch (Name[1])
482
    {
451
    {
483
    case 'L':
452
    case 'L':
Line 549... Line 518...
549
 
518
 
550
    /*
519
    /*
551
     * Add the GPE information from above to the GpeEventInfo block for
520
     * Add the GPE information from above to the GpeEventInfo block for
552
     * use during dispatch of this GPE.
521
     * use during dispatch of this GPE.
-
 
522
     */
553
     */
523
    GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK);
554
    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD);
524
    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD);
Line 555... Line -...
555
    GpeEventInfo->Dispatch.MethodNode = MethodNode;
-
 
556
 
-
 
557
    /*
-
 
558
     * Enable this GPE if requested. This only happens when during the
-
 
559
     * execution of a Load or LoadTable operator. We have found a new
-
 
560
     * GPE method and want to immediately enable the GPE if it is a
-
 
561
     * runtime GPE.
-
 
562
     */
-
 
563
    if (WalkInfo->EnableThisGpe)
-
 
564
    {
-
 
565
        /* Ignore GPEs that can wake the system */
-
 
566
 
-
 
567
        if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) ||
-
 
568
            !AcpiGbl_LeaveWakeGpesDisabled)
-
 
569
        {
-
 
570
            WalkInfo->Count++;
-
 
571
            GpeDevice = WalkInfo->GpeDevice;
-
 
572
 
-
 
573
            if (GpeDevice == AcpiGbl_FadtGpeDevice)
-
 
574
            {
-
 
575
                GpeDevice = NULL;
-
 
576
            }
-
 
577
 
-
 
578
            Status = AcpiEnableGpe (GpeDevice, GpeNumber,
-
 
579
                        ACPI_GPE_TYPE_RUNTIME);
-
 
580
            if (ACPI_FAILURE (Status))
-
 
581
            {
-
 
582
                ACPI_EXCEPTION ((AE_INFO, Status,
-
 
583
                    "Could not enable GPE 0x%02X", GpeNumber));
-
 
584
            }
-
 
585
        }
-
 
586
    }
525
    GpeEventInfo->Dispatch.MethodNode = MethodNode;
587
 
526
 
588
    ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
527
    ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
589
        "Registered GPE method %s as GPE number 0x%.2X\n",
528
        "Registered GPE method %s as GPE number 0x%.2X\n",
590
        Name, GpeNumber));
529
        Name, GpeNumber));
591
    return_ACPI_STATUS (AE_OK);
-
 
592
}
-
 
593
 
-
 
594
 
-
 
595
/*******************************************************************************
-
 
596
 *
-
 
597
 * FUNCTION:    AcpiEvMatchPrwAndGpe
-
 
598
 *
-
 
599
 * PARAMETERS:  Callback from WalkNamespace
-
 
600
 *
-
 
601
 * RETURN:      Status. NOTE: We ignore errors so that the _PRW walk is
-
 
602
 *              not aborted on a single _PRW failure.
-
 
603
 *
-
 
604
 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
-
 
605
 *              Device. Run the _PRW method. If present, extract the GPE
-
 
606
 *              number and mark the GPE as a CAN_WAKE GPE. Allows a
-
 
607
 *              per-OwnerId execution if ExecuteByOwnerId is TRUE in the
-
 
608
 *              WalkInfo parameter block.
-
 
609
 *
-
 
610
 * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that
-
 
611
 *    owner.
-
 
612
 * If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise,
-
 
613
 *    we only execute _PRWs that refer to the input GpeDevice.
-
 
614
 *
-
 
615
 ******************************************************************************/
-
 
616
 
-
 
617
ACPI_STATUS
-
 
618
AcpiEvMatchPrwAndGpe (
-
 
619
    ACPI_HANDLE             ObjHandle,
-
 
620
    UINT32                  Level,
-
 
621
    void                    *Context,
-
 
622
    void                    **ReturnValue)
-
 
623
{
-
 
624
    ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
-
 
625
    ACPI_NAMESPACE_NODE     *GpeDevice;
-
 
626
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
-
 
627
    ACPI_NAMESPACE_NODE     *TargetGpeDevice;
-
 
628
    ACPI_NAMESPACE_NODE     *PrwNode;
-
 
629
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
-
 
630
    ACPI_OPERAND_OBJECT     *PkgDesc;
-
 
631
    ACPI_OPERAND_OBJECT     *ObjDesc;
-
 
632
    UINT32                  GpeNumber;
-
 
633
    ACPI_STATUS             Status;
-
 
634
 
-
 
635
 
-
 
636
    ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);
-
 
637
 
-
 
638
 
-
 
639
    /* Check for a _PRW method under this device */
-
 
640
 
-
 
641
    Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW,
-
 
642
                ACPI_NS_NO_UPSEARCH, &PrwNode);
-
 
643
    if (ACPI_FAILURE (Status))
-
 
644
    {
-
 
645
        return_ACPI_STATUS (AE_OK);
-
 
646
    }
-
 
647
 
-
 
648
    /* Check if requested OwnerId matches this OwnerId */
-
 
649
 
-
 
650
    if ((WalkInfo->ExecuteByOwnerId) &&
-
 
651
        (PrwNode->OwnerId != WalkInfo->OwnerId))
-
 
652
    {
-
 
653
        return_ACPI_STATUS (AE_OK);
-
 
654
    }
-
 
655
 
-
 
656
    /* Execute the _PRW */
-
 
657
 
-
 
658
    Status = AcpiUtEvaluateObject (PrwNode, NULL,
-
 
659
                ACPI_BTYPE_PACKAGE, &PkgDesc);
-
 
660
    if (ACPI_FAILURE (Status))
-
 
661
    {
-
 
662
        return_ACPI_STATUS (AE_OK);
-
 
663
    }
-
 
664
 
-
 
665
    /* The returned _PRW package must have at least two elements */
-
 
666
 
-
 
667
    if (PkgDesc->Package.Count < 2)
-
 
668
    {
-
 
669
        goto Cleanup;
-
 
670
    }
-
 
671
 
-
 
672
    /* Extract pointers from the input context */
-
 
673
 
-
 
674
    GpeDevice = WalkInfo->GpeDevice;
-
 
675
    GpeBlock = WalkInfo->GpeBlock;
-
 
676
 
-
 
677
    /*
-
 
678
     * The _PRW object must return a package, we are only interested
-
 
679
     * in the first element
-
 
680
     */
-
 
681
    ObjDesc = PkgDesc->Package.Elements[0];
-
 
682
 
-
 
683
    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
-
 
684
    {
-
 
685
        /* Use FADT-defined GPE device (from definition of _PRW) */
-
 
686
 
-
 
687
        TargetGpeDevice = NULL;
-
 
688
        if (GpeDevice)
-
 
689
        {
-
 
690
            TargetGpeDevice = AcpiGbl_FadtGpeDevice;
-
 
691
        }
-
 
692
 
-
 
693
        /* Integer is the GPE number in the FADT described GPE blocks */
-
 
694
 
-
 
695
        GpeNumber = (UINT32) ObjDesc->Integer.Value;
-
 
696
    }
-
 
697
    else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
-
 
698
    {
-
 
699
        /* Package contains a GPE reference and GPE number within a GPE block */
-
 
700
 
-
 
701
        if ((ObjDesc->Package.Count < 2) ||
-
 
702
            ((ObjDesc->Package.Elements[0])->Common.Type !=
-
 
703
                ACPI_TYPE_LOCAL_REFERENCE) ||
-
 
704
            ((ObjDesc->Package.Elements[1])->Common.Type !=
-
 
705
                ACPI_TYPE_INTEGER))
-
 
706
        {
-
 
707
            goto Cleanup;
-
 
708
        }
-
 
709
 
-
 
710
        /* Get GPE block reference and decode */
-
 
711
 
-
 
712
        TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
-
 
713
        GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
-
 
714
    }
-
 
715
    else
-
 
716
    {
-
 
717
        /* Unknown type, just ignore it */
-
 
718
 
-
 
719
        goto Cleanup;
-
 
720
    }
-
 
721
 
-
 
722
    /* Get the GpeEventInfo for this GPE */
-
 
723
 
-
 
724
    if (GpeDevice)
-
 
725
    {
-
 
726
        /*
-
 
727
         * Is this GPE within this block?
-
 
728
         *
-
 
729
         * TRUE if and only if these conditions are true:
-
 
730
         *     1) The GPE devices match.
-
 
731
         *     2) The GPE index(number) is within the range of the Gpe Block
-
 
732
         *          associated with the GPE device.
-
 
733
         */
-
 
734
        if (GpeDevice != TargetGpeDevice)
-
 
735
        {
-
 
736
            goto Cleanup;
-
 
737
        }
-
 
738
 
-
 
739
        GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock);
-
 
740
    }
-
 
741
    else
-
 
742
    {
-
 
743
        /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */
-
 
744
 
-
 
745
        GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber);
-
 
746
    }
-
 
747
 
-
 
748
    if (GpeEventInfo)
-
 
749
    {
-
 
750
        if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
-
 
751
        {
-
 
752
            /* This GPE can wake the system */
-
 
753
 
-
 
754
            GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
-
 
755
            WalkInfo->Count++;
-
 
756
        }
-
 
757
    }
-
 
758
 
-
 
759
Cleanup:
-
 
760
    AcpiUtRemoveReference (PkgDesc);
-
 
761
    return_ACPI_STATUS (AE_OK);
-