Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/******************************************************************************
2
 *
3
 * Module Name: evgpe - General Purpose Event handling and dispatch
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
11
 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
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
#include "acpi.h"
117
#include "accommon.h"
118
#include "acevents.h"
119
#include "acnamesp.h"
120
 
121
#define _COMPONENT          ACPI_EVENTS
122
        ACPI_MODULE_NAME    ("evgpe")
123
 
124
/* Local prototypes */
125
 
126
static void ACPI_SYSTEM_XFACE
127
AcpiEvAsynchExecuteGpeMethod (
128
    void                    *Context);
129
 
130
static void ACPI_SYSTEM_XFACE
131
AcpiEvAsynchEnableGpe (
132
    void                    *Context);
133
 
134
 
135
/*******************************************************************************
136
 *
137
 * FUNCTION:    AcpiEvUpdateGpeEnableMasks
138
 *
139
 * PARAMETERS:  GpeEventInfo            - GPE to update
140
 *
141
 * RETURN:      Status
142
 *
143
 * DESCRIPTION: Updates GPE register enable masks based upon whether there are
144
 *              references (either wake or run) to this GPE
145
 *
146
 ******************************************************************************/
147
 
148
ACPI_STATUS
149
AcpiEvUpdateGpeEnableMasks (
150
    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
151
{
152
    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
153
    UINT8                   RegisterBit;
154
 
155
 
156
    ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
157
 
158
 
159
    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
160
    if (!GpeRegisterInfo)
161
    {
162
        return_ACPI_STATUS (AE_NOT_EXIST);
163
    }
164
 
165
    RegisterBit = (UINT8)
166
        (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
167
 
168
    /* Clear the wake/run bits up front */
169
 
170
    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
171
    ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
172
 
173
    /* Set the mask bits only if there are references to this GPE */
174
 
175
    if (GpeEventInfo->RuntimeCount)
176
    {
177
        ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
178
    }
179
 
180
    if (GpeEventInfo->WakeupCount)
181
    {
182
        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
183
    }
184
 
185
    return_ACPI_STATUS (AE_OK);
186
}
187
 
188
 
189
/*******************************************************************************
190
 *
191
 * FUNCTION:    AcpiEvEnableGpe
192
 *
193
 * PARAMETERS:  GpeEventInfo            - GPE to enable
194
 *
195
 * RETURN:      Status
196
 *
197
 * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
198
 *              of type or number of references.
199
 *
200
 * Note: The GPE lock should be already acquired when this function is called.
201
 *
202
 ******************************************************************************/
203
 
204
ACPI_STATUS
205
AcpiEvEnableGpe (
206
    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
207
{
208
    ACPI_STATUS             Status;
209
 
210
 
211
    ACPI_FUNCTION_TRACE (EvEnableGpe);
212
 
213
 
214
    /*
215
     * We will only allow a GPE to be enabled if it has either an
216
     * associated method (_Lxx/_Exx) or a handler. Otherwise, the
217
     * GPE will be immediately disabled by AcpiEvGpeDispatch the
218
     * first time it fires.
219
     */
220
    if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
221
    {
222
        return_ACPI_STATUS (AE_NO_HANDLER);
223
    }
224
 
225
    /* Ensure the HW enable masks are current */
226
 
227
    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
228
    if (ACPI_FAILURE (Status))
229
    {
230
        return_ACPI_STATUS (Status);
231
    }
232
 
233
    /* Clear the GPE (of stale events) */
234
 
235
    Status = AcpiHwClearGpe (GpeEventInfo);
236
    if (ACPI_FAILURE (Status))
237
    {
238
        return_ACPI_STATUS (Status);
239
    }
240
 
241
    /* Enable the requested GPE */
242
 
243
    Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
244
    return_ACPI_STATUS (Status);
245
}
246
 
247
 
248
/*******************************************************************************
249
 *
250
 * FUNCTION:    AcpiEvDisableGpe
251
 *
252
 * PARAMETERS:  GpeEventInfo            - GPE to disable
253
 *
254
 * RETURN:      Status
255
 *
256
 * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
257
 *              regardless of the type or number of references.
258
 *
259
 * Note: The GPE lock should be already acquired when this function is called.
260
 *
261
 ******************************************************************************/
262
 
263
ACPI_STATUS
264
AcpiEvDisableGpe (
265
    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
266
{
267
    ACPI_STATUS             Status;
268
 
269
 
270
    ACPI_FUNCTION_TRACE (EvDisableGpe);
271
 
272
 
273
    /*
274
     * Note: Always disable the GPE, even if we think that that it is already
275
     * disabled. It is possible that the AML or some other code has enabled
276
     * the GPE behind our back.
277
     */
278
 
279
    /* Ensure the HW enable masks are current */
280
 
281
    Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
282
    if (ACPI_FAILURE (Status))
283
    {
284
        return_ACPI_STATUS (Status);
285
    }
286
 
287
    /*
288
     * Always H/W disable this GPE, even if we don't know the GPE type.
289
     * Simply clear the enable bit for this particular GPE, but do not
290
     * write out the current GPE enable mask since this may inadvertently
291
     * enable GPEs too early. An example is a rogue GPE that has arrived
292
     * during ACPICA initialization - possibly because AML or other code
293
     * has enabled the GPE.
294
     */
295
    Status = AcpiHwLowDisableGpe (GpeEventInfo);
296
    return_ACPI_STATUS (Status);
297
}
298
 
299
 
300
/*******************************************************************************
301
 *
302
 * FUNCTION:    AcpiEvLowGetGpeInfo
303
 *
304
 * PARAMETERS:  GpeNumber           - Raw GPE number
305
 *              GpeBlock            - A GPE info block
306
 *
307
 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
308
 *              is not within the specified GPE block)
309
 *
310
 * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
311
 *              the low-level implementation of EvGetGpeEventInfo.
312
 *
313
 ******************************************************************************/
314
 
315
ACPI_GPE_EVENT_INFO *
316
AcpiEvLowGetGpeInfo (
317
    UINT32                  GpeNumber,
318
    ACPI_GPE_BLOCK_INFO     *GpeBlock)
319
{
320
    UINT32                  GpeIndex;
321
 
322
 
323
    /*
324
     * Validate that the GpeNumber is within the specified GpeBlock.
325
     * (Two steps)
326
     */
327
    if (!GpeBlock ||
328
        (GpeNumber < GpeBlock->BlockBaseNumber))
329
    {
330
        return (NULL);
331
    }
332
 
333
    GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
334
    if (GpeIndex >= GpeBlock->GpeCount)
335
    {
336
        return (NULL);
337
    }
338
 
339
    return (&GpeBlock->EventInfo[GpeIndex]);
340
}
341
 
342
 
343
/*******************************************************************************
344
 *
345
 * FUNCTION:    AcpiEvGetGpeEventInfo
346
 *
347
 * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
348
 *              GpeNumber           - Raw GPE number
349
 *
350
 * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
351
 *
352
 * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
353
 *              Validates the GpeBlock and the GpeNumber
354
 *
355
 *              Should be called only when the GPE lists are semaphore locked
356
 *              and not subject to change.
357
 *
358
 ******************************************************************************/
359
 
360
ACPI_GPE_EVENT_INFO *
361
AcpiEvGetGpeEventInfo (
362
    ACPI_HANDLE             GpeDevice,
363
    UINT32                  GpeNumber)
364
{
365
    ACPI_OPERAND_OBJECT     *ObjDesc;
366
    ACPI_GPE_EVENT_INFO     *GpeInfo;
367
    UINT32                  i;
368
 
369
 
370
    ACPI_FUNCTION_ENTRY ();
371
 
372
 
373
    /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
374
 
375
    if (!GpeDevice)
376
    {
377
        /* Examine GPE Block 0 and 1 (These blocks are permanent) */
378
 
379
        for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
380
        {
381
            GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
382
                        AcpiGbl_GpeFadtBlocks[i]);
383
            if (GpeInfo)
384
            {
385
                return (GpeInfo);
386
            }
387
        }
388
 
389
        /* The GpeNumber was not in the range of either FADT GPE block */
390
 
391
        return (NULL);
392
    }
393
 
394
    /* A Non-NULL GpeDevice means this is a GPE Block Device */
395
 
396
    ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
397
    if (!ObjDesc ||
398
        !ObjDesc->Device.GpeBlock)
399
    {
400
        return (NULL);
401
    }
402
 
403
    return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
404
}
405
 
406
 
407
/*******************************************************************************
408
 *
409
 * FUNCTION:    AcpiEvGpeDetect
410
 *
411
 * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
412
 *                                    Can have multiple GPE blocks attached.
413
 *
414
 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
415
 *
416
 * DESCRIPTION: Detect if any GP events have occurred. This function is
417
 *              executed at interrupt level.
418
 *
419
 ******************************************************************************/
420
 
421
UINT32
422
AcpiEvGpeDetect (
423
    ACPI_GPE_XRUPT_INFO     *GpeXruptList)
424
{
425
    ACPI_STATUS             Status;
426
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
427
    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
428
    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
429
    UINT8                   EnabledStatusByte;
430
    UINT32                  StatusReg;
431
    UINT32                  EnableReg;
432
    ACPI_CPU_FLAGS          Flags;
433
    UINT32                  i;
434
    UINT32                  j;
435
 
436
 
437
    ACPI_FUNCTION_NAME (EvGpeDetect);
438
 
439
    /* Check for the case where there are no GPEs */
440
 
441
    if (!GpeXruptList)
442
    {
443
        return (IntStatus);
444
    }
445
 
446
    /*
447
     * We need to obtain the GPE lock for both the data structs and registers
448
     * Note: Not necessary to obtain the hardware lock, since the GPE
449
     * registers are owned by the GpeLock.
450
     */
451
    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
452
 
453
    /* Examine all GPE blocks attached to this interrupt level */
454
 
455
    GpeBlock = GpeXruptList->GpeBlockListHead;
456
    while (GpeBlock)
457
    {
458
        /*
459
         * Read all of the 8-bit GPE status and enable registers in this GPE
460
         * block, saving all of them. Find all currently active GP events.
461
         */
462
        for (i = 0; i < GpeBlock->RegisterCount; i++)
463
        {
464
            /* Get the next status/enable pair */
465
 
466
            GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
467
 
468
            /* Read the Status Register */
469
 
470
            Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
471
            if (ACPI_FAILURE (Status))
472
            {
473
                goto UnlockAndExit;
474
            }
475
 
476
            /* Read the Enable Register */
477
 
478
            Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
479
            if (ACPI_FAILURE (Status))
480
            {
481
                goto UnlockAndExit;
482
            }
483
 
484
            ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
485
                "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
486
                GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
487
 
488
            /* Check if there is anything active at all in this register */
489
 
490
            EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
491
            if (!EnabledStatusByte)
492
            {
493
                /* No active GPEs in this register, move on */
494
 
495
                continue;
496
            }
497
 
498
            /* Now look at the individual GPEs in this byte register */
499
 
500
            for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
501
            {
502
                /* Examine one GPE bit */
503
 
504
                if (EnabledStatusByte & (1 << j))
505
                {
506
                    /*
507
                     * Found an active GPE. Dispatch the event to a handler
508
                     * or method.
509
                     */
510
                    IntStatus |= AcpiEvGpeDispatch (
511
                        &GpeBlock->EventInfo[((ACPI_SIZE) i *
512
                            ACPI_GPE_REGISTER_WIDTH) + j],
513
                        j + GpeRegisterInfo->BaseGpeNumber);
514
                }
515
            }
516
        }
517
 
518
        GpeBlock = GpeBlock->Next;
519
    }
520
 
521
UnlockAndExit:
522
 
523
    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
524
    return (IntStatus);
525
}
526
 
527
 
528
/*******************************************************************************
529
 *
530
 * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
531
 *
532
 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
533
 *
534
 * RETURN:      None
535
 *
536
 * DESCRIPTION: Perform the actual execution of a GPE control method. This
537
 *              function is called from an invocation of AcpiOsExecute and
538
 *              therefore does NOT execute at interrupt level - so that
539
 *              the control method itself is not executed in the context of
540
 *              an interrupt handler.
541
 *
542
 ******************************************************************************/
543
 
544
static void ACPI_SYSTEM_XFACE
545
AcpiEvAsynchExecuteGpeMethod (
546
    void                    *Context)
547
{
548
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
549
    ACPI_STATUS             Status;
550
    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
551
    ACPI_EVALUATE_INFO      *Info;
552
 
553
 
554
    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
555
 
556
 
557
    /* Allocate a local GPE block */
558
 
559
    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
560
    if (!LocalGpeEventInfo)
561
    {
562
        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
563
            "while handling a GPE"));
564
        return_VOID;
565
    }
566
 
567
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
568
    if (ACPI_FAILURE (Status))
569
    {
570
        return_VOID;
571
    }
572
 
573
    /* Must revalidate the GpeNumber/GpeBlock */
574
 
575
    if (!AcpiEvValidGpeEvent (GpeEventInfo))
576
    {
577
        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
578
        return_VOID;
579
    }
580
 
581
    /* Update the GPE register masks for return to enabled state */
582
 
583
    (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
584
 
585
    /*
586
     * Take a snapshot of the GPE info for this level - we copy the info to
587
     * prevent a race condition with RemoveHandler/RemoveBlock.
588
     */
589
    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
590
        sizeof (ACPI_GPE_EVENT_INFO));
591
 
592
    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
593
    if (ACPI_FAILURE (Status))
594
    {
595
        return_VOID;
596
    }
597
 
598
    /*
599
     * Must check for control method type dispatch one more time to avoid a
600
     * race with EvGpeInstallHandler
601
     */
602
    if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
603
            ACPI_GPE_DISPATCH_METHOD)
604
    {
605
        /* Allocate the evaluation information block */
606
 
607
        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
608
        if (!Info)
609
        {
610
            Status = AE_NO_MEMORY;
611
        }
612
        else
613
        {
614
            /*
615
             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
616
             * control method that corresponds to this GPE
617
             */
618
            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
619
            Info->Flags = ACPI_IGNORE_RETURN_VALUE;
620
 
621
            Status = AcpiNsEvaluate (Info);
622
            ACPI_FREE (Info);
623
        }
624
 
625
        if (ACPI_FAILURE (Status))
626
        {
627
            ACPI_EXCEPTION ((AE_INFO, Status,
628
                "while evaluating GPE method [%4.4s]",
629
                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
630
        }
631
    }
632
 
633
    /* Defer enabling of GPE until all notify handlers are done */
634
 
635
    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
636
                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
637
    if (ACPI_FAILURE (Status))
638
    {
639
        ACPI_FREE (LocalGpeEventInfo);
640
    }
641
    return_VOID;
642
}
643
 
644
 
645
/*******************************************************************************
646
 *
647
 * FUNCTION:    AcpiEvAsynchEnableGpe
648
 *
649
 * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
650
 *
651
 * RETURN:      None
652
 *
653
 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
654
 *              complete (i.e., finish execution of Notify)
655
 *
656
 ******************************************************************************/
657
 
658
static void ACPI_SYSTEM_XFACE
659
AcpiEvAsynchEnableGpe (
660
    void                    *Context)
661
{
662
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
663
    ACPI_STATUS             Status;
664
 
665
 
666
    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
667
            ACPI_GPE_LEVEL_TRIGGERED)
668
    {
669
        /*
670
         * GPE is level-triggered, we clear the GPE status bit after handling
671
         * the event.
672
         */
673
        Status = AcpiHwClearGpe (GpeEventInfo);
674
        if (ACPI_FAILURE (Status))
675
        {
676
            goto Exit;
677
        }
678
    }
679
 
680
    /* Enable this GPE */
681
 
682
    (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
683
 
684
Exit:
685
    ACPI_FREE (GpeEventInfo);
686
    return;
687
}
688
 
689
 
690
/*******************************************************************************
691
 *
692
 * FUNCTION:    AcpiEvGpeDispatch
693
 *
694
 * PARAMETERS:  GpeEventInfo    - Info for this GPE
695
 *              GpeNumber       - Number relative to the parent GPE block
696
 *
697
 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
698
 *
699
 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
700
 *              or method (e.g. _Lxx/_Exx) handler.
701
 *
702
 *              This function executes at interrupt level.
703
 *
704
 ******************************************************************************/
705
 
706
UINT32
707
AcpiEvGpeDispatch (
708
    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
709
    UINT32                  GpeNumber)
710
{
711
    ACPI_STATUS             Status;
712
 
713
 
714
    ACPI_FUNCTION_TRACE (EvGpeDispatch);
715
 
716
 
717
    AcpiGpeCount++;
718
 
719
    /*
720
     * If edge-triggered, clear the GPE status bit now. Note that
721
     * level-triggered events are cleared after the GPE is serviced.
722
     */
723
    if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
724
            ACPI_GPE_EDGE_TRIGGERED)
725
    {
726
        Status = AcpiHwClearGpe (GpeEventInfo);
727
        if (ACPI_FAILURE (Status))
728
        {
729
            ACPI_EXCEPTION ((AE_INFO, Status,
730
                "Unable to clear GPE[0x%2X]", GpeNumber));
731
            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
732
        }
733
    }
734
 
735
    /*
736
     * Dispatch the GPE to either an installed handler, or the control method
737
     * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
738
     * it and do not attempt to run the method. If there is neither a handler
739
     * nor a method, we disable this GPE to prevent further such pointless
740
     * events from firing.
741
     */
742
    switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
743
    {
744
    case ACPI_GPE_DISPATCH_HANDLER:
745
 
746
        /*
747
         * Invoke the installed handler (at interrupt level)
748
         * Ignore return status for now.
749
         * TBD: leave GPE disabled on error?
750
         */
751
        (void) GpeEventInfo->Dispatch.Handler->Address (
752
                        GpeEventInfo->Dispatch.Handler->Context);
753
 
754
        /* It is now safe to clear level-triggered events. */
755
 
756
        if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
757
                ACPI_GPE_LEVEL_TRIGGERED)
758
        {
759
            Status = AcpiHwClearGpe (GpeEventInfo);
760
            if (ACPI_FAILURE (Status))
761
            {
762
                ACPI_EXCEPTION ((AE_INFO, Status,
763
                    "Unable to clear GPE[0x%2X]", GpeNumber));
764
                return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
765
            }
766
        }
767
        break;
768
 
769
    case ACPI_GPE_DISPATCH_METHOD:
770
 
771
        /*
772
         * Disable the GPE, so it doesn't keep firing before the method has a
773
         * chance to run (it runs asynchronously with interrupts enabled).
774
         */
775
        Status = AcpiEvDisableGpe (GpeEventInfo);
776
        if (ACPI_FAILURE (Status))
777
        {
778
            ACPI_EXCEPTION ((AE_INFO, Status,
779
                "Unable to disable GPE[0x%2X]", GpeNumber));
780
            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
781
        }
782
 
783
        /*
784
         * Execute the method associated with the GPE
785
         * NOTE: Level-triggered GPEs are cleared after the method completes.
786
         */
787
        Status = AcpiOsExecute (OSL_GPE_HANDLER,
788
                    AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
789
        if (ACPI_FAILURE (Status))
790
        {
791
            ACPI_EXCEPTION ((AE_INFO, Status,
792
                "Unable to queue handler for GPE[0x%2X] - event disabled",
793
                GpeNumber));
794
        }
795
        break;
796
 
797
    default:
798
 
799
        /*
800
         * No handler or method to run!
801
         * 03/2010: This case should no longer be possible. We will not allow
802
         * a GPE to be enabled if it has no handler or method.
803
         */
804
        ACPI_ERROR ((AE_INFO,
805
            "No handler or method for GPE[0x%2X], disabling event",
806
            GpeNumber));
807
 
808
        /*
809
         * Disable the GPE. The GPE will remain disabled a handler
810
         * is installed or ACPICA is restarted.
811
         */
812
        Status = AcpiEvDisableGpe (GpeEventInfo);
813
        if (ACPI_FAILURE (Status))
814
        {
815
            ACPI_EXCEPTION ((AE_INFO, Status,
816
                "Unable to disable GPE[0x%2X]", GpeNumber));
817
            return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
818
        }
819
        break;
820
    }
821
 
822
    return_UINT32 (ACPI_INTERRUPT_HANDLED);
823
}
824