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