evgpeblk.c revision 193341
1/******************************************************************************
2 *
3 * Module Name: evgpeblk - GPE block creation and initialization.
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2009, 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 <contrib/dev/acpica/include/acpi.h>
117#include <contrib/dev/acpica/include/accommon.h>
118#include <contrib/dev/acpica/include/acevents.h>
119#include <contrib/dev/acpica/include/acnamesp.h>
120
121#define _COMPONENT          ACPI_EVENTS
122        ACPI_MODULE_NAME    ("evgpeblk")
123
124/* Local prototypes */
125
126static ACPI_STATUS
127AcpiEvSaveMethodInfo (
128    ACPI_HANDLE             ObjHandle,
129    UINT32                  Level,
130    void                    *ObjDesc,
131    void                    **ReturnValue);
132
133static ACPI_STATUS
134AcpiEvMatchPrwAndGpe (
135    ACPI_HANDLE             ObjHandle,
136    UINT32                  Level,
137    void                    *Info,
138    void                    **ReturnValue);
139
140static ACPI_GPE_XRUPT_INFO *
141AcpiEvGetGpeXruptBlock (
142    UINT32                  InterruptNumber);
143
144static ACPI_STATUS
145AcpiEvDeleteGpeXrupt (
146    ACPI_GPE_XRUPT_INFO     *GpeXrupt);
147
148static ACPI_STATUS
149AcpiEvInstallGpeBlock (
150    ACPI_GPE_BLOCK_INFO     *GpeBlock,
151    UINT32                  InterruptNumber);
152
153static ACPI_STATUS
154AcpiEvCreateGpeInfoBlocks (
155    ACPI_GPE_BLOCK_INFO     *GpeBlock);
156
157
158/*******************************************************************************
159 *
160 * FUNCTION:    AcpiEvValidGpeEvent
161 *
162 * PARAMETERS:  GpeEventInfo                - Info for this GPE
163 *
164 * RETURN:      TRUE if the GpeEvent is valid
165 *
166 * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
167 *              Should be called only when the GPE lists are semaphore locked
168 *              and not subject to change.
169 *
170 ******************************************************************************/
171
172BOOLEAN
173AcpiEvValidGpeEvent (
174    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
175{
176    ACPI_GPE_XRUPT_INFO     *GpeXruptBlock;
177    ACPI_GPE_BLOCK_INFO     *GpeBlock;
178
179
180    ACPI_FUNCTION_ENTRY ();
181
182
183    /* No need for spin lock since we are not changing any list elements */
184
185    /* Walk the GPE interrupt levels */
186
187    GpeXruptBlock = AcpiGbl_GpeXruptListHead;
188    while (GpeXruptBlock)
189    {
190        GpeBlock = GpeXruptBlock->GpeBlockListHead;
191
192        /* Walk the GPE blocks on this interrupt level */
193
194        while (GpeBlock)
195        {
196            if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) &&
197                (&GpeBlock->EventInfo[((ACPI_SIZE)
198                    GpeBlock->RegisterCount) * 8] > GpeEventInfo))
199            {
200                return (TRUE);
201            }
202
203            GpeBlock = GpeBlock->Next;
204        }
205
206        GpeXruptBlock = GpeXruptBlock->Next;
207    }
208
209    return (FALSE);
210}
211
212
213/*******************************************************************************
214 *
215 * FUNCTION:    AcpiEvWalkGpeList
216 *
217 * PARAMETERS:  GpeWalkCallback     - Routine called for each GPE block
218 *              Context             - Value passed to callback
219 *
220 * RETURN:      Status
221 *
222 * DESCRIPTION: Walk the GPE lists.
223 *
224 ******************************************************************************/
225
226ACPI_STATUS
227AcpiEvWalkGpeList (
228    ACPI_GPE_CALLBACK       GpeWalkCallback,
229    void                    *Context)
230{
231    ACPI_GPE_BLOCK_INFO     *GpeBlock;
232    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
233    ACPI_STATUS             Status = AE_OK;
234    ACPI_CPU_FLAGS          Flags;
235
236
237    ACPI_FUNCTION_TRACE (EvWalkGpeList);
238
239
240    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
241
242    /* Walk the interrupt level descriptor list */
243
244    GpeXruptInfo = AcpiGbl_GpeXruptListHead;
245    while (GpeXruptInfo)
246    {
247        /* Walk all Gpe Blocks attached to this interrupt level */
248
249        GpeBlock = GpeXruptInfo->GpeBlockListHead;
250        while (GpeBlock)
251        {
252            /* One callback per GPE block */
253
254            Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context);
255            if (ACPI_FAILURE (Status))
256            {
257                if (Status == AE_CTRL_END) /* Callback abort */
258                {
259                    Status = AE_OK;
260                }
261                goto UnlockAndExit;
262            }
263
264            GpeBlock = GpeBlock->Next;
265        }
266
267        GpeXruptInfo = GpeXruptInfo->Next;
268    }
269
270UnlockAndExit:
271    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
272    return_ACPI_STATUS (Status);
273}
274
275
276/*******************************************************************************
277 *
278 * FUNCTION:    AcpiEvDeleteGpeHandlers
279 *
280 * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
281 *              GpeBlock            - Gpe Block info
282 *
283 * RETURN:      Status
284 *
285 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
286 *              Used only prior to termination.
287 *
288 ******************************************************************************/
289
290ACPI_STATUS
291AcpiEvDeleteGpeHandlers (
292    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
293    ACPI_GPE_BLOCK_INFO     *GpeBlock,
294    void                    *Context)
295{
296    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
297    UINT32                  i;
298    UINT32                  j;
299
300
301    ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
302
303
304    /* Examine each GPE Register within the block */
305
306    for (i = 0; i < GpeBlock->RegisterCount; i++)
307    {
308        /* Now look at the individual GPEs in this byte register */
309
310        for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
311        {
312            GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
313                ACPI_GPE_REGISTER_WIDTH) + j];
314
315            if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
316                    ACPI_GPE_DISPATCH_HANDLER)
317            {
318                ACPI_FREE (GpeEventInfo->Dispatch.Handler);
319                GpeEventInfo->Dispatch.Handler = NULL;
320                GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
321            }
322        }
323    }
324
325    return_ACPI_STATUS (AE_OK);
326}
327
328
329/*******************************************************************************
330 *
331 * FUNCTION:    AcpiEvSaveMethodInfo
332 *
333 * PARAMETERS:  Callback from WalkNamespace
334 *
335 * RETURN:      Status
336 *
337 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
338 *              control method under the _GPE portion of the namespace.
339 *              Extract the name and GPE type from the object, saving this
340 *              information for quick lookup during GPE dispatch
341 *
342 *              The name of each GPE control method is of the form:
343 *              "_Lxx" or "_Exx"
344 *              Where:
345 *                  L      - means that the GPE is level triggered
346 *                  E      - means that the GPE is edge triggered
347 *                  xx     - is the GPE number [in HEX]
348 *
349 ******************************************************************************/
350
351static ACPI_STATUS
352AcpiEvSaveMethodInfo (
353    ACPI_HANDLE             ObjHandle,
354    UINT32                  Level,
355    void                    *ObjDesc,
356    void                    **ReturnValue)
357{
358    ACPI_GPE_BLOCK_INFO     *GpeBlock = (void *) ObjDesc;
359    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
360    UINT32                  GpeNumber;
361    char                    Name[ACPI_NAME_SIZE + 1];
362    UINT8                   Type;
363    ACPI_STATUS             Status;
364
365
366    ACPI_FUNCTION_TRACE (EvSaveMethodInfo);
367
368
369    /*
370     * _Lxx and _Exx GPE method support
371     *
372     * 1) Extract the name from the object and convert to a string
373     */
374    ACPI_MOVE_32_TO_32 (
375        Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer);
376    Name[ACPI_NAME_SIZE] = 0;
377
378    /*
379     * 2) Edge/Level determination is based on the 2nd character
380     *    of the method name
381     *
382     * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
383     * if a _PRW object is found that points to this GPE.
384     */
385    switch (Name[1])
386    {
387    case 'L':
388        Type = ACPI_GPE_LEVEL_TRIGGERED;
389        break;
390
391    case 'E':
392        Type = ACPI_GPE_EDGE_TRIGGERED;
393        break;
394
395    default:
396        /* Unknown method type, just ignore it! */
397
398        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
399            "Ignoring unknown GPE method type: %s "
400            "(name not of form _Lxx or _Exx)",
401            Name));
402        return_ACPI_STATUS (AE_OK);
403    }
404
405    /* Convert the last two characters of the name to the GPE Number */
406
407    GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
408    if (GpeNumber == ACPI_UINT32_MAX)
409    {
410        /* Conversion failed; invalid method, just ignore it */
411
412        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
413            "Could not extract GPE number from name: %s "
414            "(name is not of form _Lxx or _Exx)",
415            Name));
416        return_ACPI_STATUS (AE_OK);
417    }
418
419    /* Ensure that we have a valid GPE number for this GPE block */
420
421    if ((GpeNumber < GpeBlock->BlockBaseNumber) ||
422        (GpeNumber >= (GpeBlock->BlockBaseNumber +
423            (GpeBlock->RegisterCount * 8))))
424    {
425        /*
426         * Not valid for this GPE block, just ignore it. However, it may be
427         * valid for a different GPE block, since GPE0 and GPE1 methods both
428         * appear under \_GPE.
429         */
430        return_ACPI_STATUS (AE_OK);
431    }
432
433    /*
434     * Now we can add this information to the GpeEventInfo block for use
435     * during dispatch of this GPE. Default type is RUNTIME, although this may
436     * change when the _PRW methods are executed later.
437     */
438    GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber];
439
440    GpeEventInfo->Flags = (UINT8)
441        (Type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
442
443    GpeEventInfo->Dispatch.MethodNode = (ACPI_NAMESPACE_NODE *) ObjHandle;
444
445    /* Update enable mask, but don't enable the HW GPE as of yet */
446
447    Status = AcpiEvEnableGpe (GpeEventInfo, FALSE);
448
449    ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
450        "Registered GPE method %s as GPE number 0x%.2X\n",
451        Name, GpeNumber));
452    return_ACPI_STATUS (Status);
453}
454
455
456/*******************************************************************************
457 *
458 * FUNCTION:    AcpiEvMatchPrwAndGpe
459 *
460 * PARAMETERS:  Callback from WalkNamespace
461 *
462 * RETURN:      Status. NOTE: We ignore errors so that the _PRW walk is
463 *              not aborted on a single _PRW failure.
464 *
465 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
466 *              Device. Run the _PRW method. If present, extract the GPE
467 *              number and mark the GPE as a WAKE GPE.
468 *
469 ******************************************************************************/
470
471static ACPI_STATUS
472AcpiEvMatchPrwAndGpe (
473    ACPI_HANDLE             ObjHandle,
474    UINT32                  Level,
475    void                    *Info,
476    void                    **ReturnValue)
477{
478    ACPI_GPE_WALK_INFO      *GpeInfo = (void *) Info;
479    ACPI_NAMESPACE_NODE     *GpeDevice;
480    ACPI_GPE_BLOCK_INFO     *GpeBlock;
481    ACPI_NAMESPACE_NODE     *TargetGpeDevice;
482    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
483    ACPI_OPERAND_OBJECT     *PkgDesc;
484    ACPI_OPERAND_OBJECT     *ObjDesc;
485    UINT32                  GpeNumber;
486    ACPI_STATUS             Status;
487
488
489    ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);
490
491
492    /* Check for a _PRW method under this device */
493
494    Status = AcpiUtEvaluateObject (ObjHandle, METHOD_NAME__PRW,
495                ACPI_BTYPE_PACKAGE, &PkgDesc);
496    if (ACPI_FAILURE (Status))
497    {
498        /* Ignore all errors from _PRW, we don't want to abort the subsystem */
499
500        return_ACPI_STATUS (AE_OK);
501    }
502
503    /* The returned _PRW package must have at least two elements */
504
505    if (PkgDesc->Package.Count < 2)
506    {
507        goto Cleanup;
508    }
509
510    /* Extract pointers from the input context */
511
512    GpeDevice = GpeInfo->GpeDevice;
513    GpeBlock = GpeInfo->GpeBlock;
514
515    /*
516     * The _PRW object must return a package, we are only interested in the
517     * first element
518     */
519    ObjDesc = PkgDesc->Package.Elements[0];
520
521    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
522    {
523        /* Use FADT-defined GPE device (from definition of _PRW) */
524
525        TargetGpeDevice = AcpiGbl_FadtGpeDevice;
526
527        /* Integer is the GPE number in the FADT described GPE blocks */
528
529        GpeNumber = (UINT32) ObjDesc->Integer.Value;
530    }
531    else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
532    {
533        /* Package contains a GPE reference and GPE number within a GPE block */
534
535        if ((ObjDesc->Package.Count < 2) ||
536            ((ObjDesc->Package.Elements[0])->Common.Type !=
537                ACPI_TYPE_LOCAL_REFERENCE) ||
538            ((ObjDesc->Package.Elements[1])->Common.Type !=
539                ACPI_TYPE_INTEGER))
540        {
541            goto Cleanup;
542        }
543
544        /* Get GPE block reference and decode */
545
546        TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
547        GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
548    }
549    else
550    {
551        /* Unknown type, just ignore it */
552
553        goto Cleanup;
554    }
555
556    /*
557     * Is this GPE within this block?
558     *
559     * TRUE if and only if these conditions are true:
560     *     1) The GPE devices match.
561     *     2) The GPE index(number) is within the range of the Gpe Block
562     *          associated with the GPE device.
563     */
564    if ((GpeDevice == TargetGpeDevice) &&
565        (GpeNumber >= GpeBlock->BlockBaseNumber) &&
566        (GpeNumber < GpeBlock->BlockBaseNumber +
567            (GpeBlock->RegisterCount * 8)))
568    {
569        GpeEventInfo = &GpeBlock->EventInfo[GpeNumber -
570            GpeBlock->BlockBaseNumber];
571
572        /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
573
574        GpeEventInfo->Flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
575
576        Status = AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE);
577        if (ACPI_FAILURE (Status))
578        {
579            goto Cleanup;
580        }
581
582        Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
583    }
584
585Cleanup:
586    AcpiUtRemoveReference (PkgDesc);
587    return_ACPI_STATUS (AE_OK);
588}
589
590
591/*******************************************************************************
592 *
593 * FUNCTION:    AcpiEvGetGpeXruptBlock
594 *
595 * PARAMETERS:  InterruptNumber      - Interrupt for a GPE block
596 *
597 * RETURN:      A GPE interrupt block
598 *
599 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
600 *              block per unique interrupt level used for GPEs. Should be
601 *              called only when the GPE lists are semaphore locked and not
602 *              subject to change.
603 *
604 ******************************************************************************/
605
606static ACPI_GPE_XRUPT_INFO *
607AcpiEvGetGpeXruptBlock (
608    UINT32                  InterruptNumber)
609{
610    ACPI_GPE_XRUPT_INFO     *NextGpeXrupt;
611    ACPI_GPE_XRUPT_INFO     *GpeXrupt;
612    ACPI_STATUS             Status;
613    ACPI_CPU_FLAGS          Flags;
614
615
616    ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
617
618
619    /* No need for lock since we are not changing any list elements here */
620
621    NextGpeXrupt = AcpiGbl_GpeXruptListHead;
622    while (NextGpeXrupt)
623    {
624        if (NextGpeXrupt->InterruptNumber == InterruptNumber)
625        {
626            return_PTR (NextGpeXrupt);
627        }
628
629        NextGpeXrupt = NextGpeXrupt->Next;
630    }
631
632    /* Not found, must allocate a new xrupt descriptor */
633
634    GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
635    if (!GpeXrupt)
636    {
637        return_PTR (NULL);
638    }
639
640    GpeXrupt->InterruptNumber = InterruptNumber;
641
642    /* Install new interrupt descriptor with spin lock */
643
644    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
645    if (AcpiGbl_GpeXruptListHead)
646    {
647        NextGpeXrupt = AcpiGbl_GpeXruptListHead;
648        while (NextGpeXrupt->Next)
649        {
650            NextGpeXrupt = NextGpeXrupt->Next;
651        }
652
653        NextGpeXrupt->Next = GpeXrupt;
654        GpeXrupt->Previous = NextGpeXrupt;
655    }
656    else
657    {
658        AcpiGbl_GpeXruptListHead = GpeXrupt;
659    }
660    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
661
662    /* Install new interrupt handler if not SCI_INT */
663
664    if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
665    {
666        Status = AcpiOsInstallInterruptHandler (InterruptNumber,
667                    AcpiEvGpeXruptHandler, GpeXrupt);
668        if (ACPI_FAILURE (Status))
669        {
670            ACPI_ERROR ((AE_INFO,
671                "Could not install GPE interrupt handler at level 0x%X",
672                InterruptNumber));
673            return_PTR (NULL);
674        }
675    }
676
677    return_PTR (GpeXrupt);
678}
679
680
681/*******************************************************************************
682 *
683 * FUNCTION:    AcpiEvDeleteGpeXrupt
684 *
685 * PARAMETERS:  GpeXrupt        - A GPE interrupt info block
686 *
687 * RETURN:      Status
688 *
689 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
690 *              interrupt handler if not the SCI interrupt.
691 *
692 ******************************************************************************/
693
694static ACPI_STATUS
695AcpiEvDeleteGpeXrupt (
696    ACPI_GPE_XRUPT_INFO     *GpeXrupt)
697{
698    ACPI_STATUS             Status;
699    ACPI_CPU_FLAGS          Flags;
700
701
702    ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt);
703
704
705    /* We never want to remove the SCI interrupt handler */
706
707    if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt)
708    {
709        GpeXrupt->GpeBlockListHead = NULL;
710        return_ACPI_STATUS (AE_OK);
711    }
712
713    /* Disable this interrupt */
714
715    Status = AcpiOsRemoveInterruptHandler (
716                GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler);
717    if (ACPI_FAILURE (Status))
718    {
719        return_ACPI_STATUS (Status);
720    }
721
722    /* Unlink the interrupt block with lock */
723
724    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
725    if (GpeXrupt->Previous)
726    {
727        GpeXrupt->Previous->Next = GpeXrupt->Next;
728    }
729    else
730    {
731        /* No previous, update list head */
732
733        AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
734    }
735
736    if (GpeXrupt->Next)
737    {
738        GpeXrupt->Next->Previous = GpeXrupt->Previous;
739    }
740    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
741
742    /* Free the block */
743
744    ACPI_FREE (GpeXrupt);
745    return_ACPI_STATUS (AE_OK);
746}
747
748
749/*******************************************************************************
750 *
751 * FUNCTION:    AcpiEvInstallGpeBlock
752 *
753 * PARAMETERS:  GpeBlock                - New GPE block
754 *              InterruptNumber         - Xrupt to be associated with this
755 *                                        GPE block
756 *
757 * RETURN:      Status
758 *
759 * DESCRIPTION: Install new GPE block with mutex support
760 *
761 ******************************************************************************/
762
763static ACPI_STATUS
764AcpiEvInstallGpeBlock (
765    ACPI_GPE_BLOCK_INFO     *GpeBlock,
766    UINT32                  InterruptNumber)
767{
768    ACPI_GPE_BLOCK_INFO     *NextGpeBlock;
769    ACPI_GPE_XRUPT_INFO     *GpeXruptBlock;
770    ACPI_STATUS             Status;
771    ACPI_CPU_FLAGS          Flags;
772
773
774    ACPI_FUNCTION_TRACE (EvInstallGpeBlock);
775
776
777    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
778    if (ACPI_FAILURE (Status))
779    {
780        return_ACPI_STATUS (Status);
781    }
782
783    GpeXruptBlock = AcpiEvGetGpeXruptBlock (InterruptNumber);
784    if (!GpeXruptBlock)
785    {
786        Status = AE_NO_MEMORY;
787        goto UnlockAndExit;
788    }
789
790    /* Install the new block at the end of the list with lock */
791
792    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
793    if (GpeXruptBlock->GpeBlockListHead)
794    {
795        NextGpeBlock = GpeXruptBlock->GpeBlockListHead;
796        while (NextGpeBlock->Next)
797        {
798            NextGpeBlock = NextGpeBlock->Next;
799        }
800
801        NextGpeBlock->Next = GpeBlock;
802        GpeBlock->Previous = NextGpeBlock;
803    }
804    else
805    {
806        GpeXruptBlock->GpeBlockListHead = GpeBlock;
807    }
808
809    GpeBlock->XruptBlock = GpeXruptBlock;
810    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
811
812
813UnlockAndExit:
814    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
815    return_ACPI_STATUS (Status);
816}
817
818
819/*******************************************************************************
820 *
821 * FUNCTION:    AcpiEvDeleteGpeBlock
822 *
823 * PARAMETERS:  GpeBlock            - Existing GPE block
824 *
825 * RETURN:      Status
826 *
827 * DESCRIPTION: Remove a GPE block
828 *
829 ******************************************************************************/
830
831ACPI_STATUS
832AcpiEvDeleteGpeBlock (
833    ACPI_GPE_BLOCK_INFO     *GpeBlock)
834{
835    ACPI_STATUS             Status;
836    ACPI_CPU_FLAGS          Flags;
837
838
839    ACPI_FUNCTION_TRACE (EvInstallGpeBlock);
840
841
842    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
843    if (ACPI_FAILURE (Status))
844    {
845        return_ACPI_STATUS (Status);
846    }
847
848    /* Disable all GPEs in this block */
849
850    Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL);
851
852    if (!GpeBlock->Previous && !GpeBlock->Next)
853    {
854        /* This is the last GpeBlock on this interrupt */
855
856        Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock);
857        if (ACPI_FAILURE (Status))
858        {
859            goto UnlockAndExit;
860        }
861    }
862    else
863    {
864        /* Remove the block on this interrupt with lock */
865
866        Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
867        if (GpeBlock->Previous)
868        {
869            GpeBlock->Previous->Next = GpeBlock->Next;
870        }
871        else
872        {
873            GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next;
874        }
875
876        if (GpeBlock->Next)
877        {
878            GpeBlock->Next->Previous = GpeBlock->Previous;
879        }
880        AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
881    }
882
883    AcpiCurrentGpeCount -= GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH;
884
885    /* Free the GpeBlock */
886
887    ACPI_FREE (GpeBlock->RegisterInfo);
888    ACPI_FREE (GpeBlock->EventInfo);
889    ACPI_FREE (GpeBlock);
890
891UnlockAndExit:
892    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
893    return_ACPI_STATUS (Status);
894}
895
896
897/*******************************************************************************
898 *
899 * FUNCTION:    AcpiEvCreateGpeInfoBlocks
900 *
901 * PARAMETERS:  GpeBlock    - New GPE block
902 *
903 * RETURN:      Status
904 *
905 * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block
906 *
907 ******************************************************************************/
908
909static ACPI_STATUS
910AcpiEvCreateGpeInfoBlocks (
911    ACPI_GPE_BLOCK_INFO     *GpeBlock)
912{
913    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo = NULL;
914    ACPI_GPE_EVENT_INFO     *GpeEventInfo = NULL;
915    ACPI_GPE_EVENT_INFO     *ThisEvent;
916    ACPI_GPE_REGISTER_INFO  *ThisRegister;
917    UINT32                  i;
918    UINT32                  j;
919    ACPI_STATUS             Status;
920
921
922    ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks);
923
924
925    /* Allocate the GPE register information block */
926
927    GpeRegisterInfo = ACPI_ALLOCATE_ZEROED (
928                            (ACPI_SIZE) GpeBlock->RegisterCount *
929                            sizeof (ACPI_GPE_REGISTER_INFO));
930    if (!GpeRegisterInfo)
931    {
932        ACPI_ERROR ((AE_INFO,
933            "Could not allocate the GpeRegisterInfo table"));
934        return_ACPI_STATUS (AE_NO_MEMORY);
935    }
936
937    /*
938     * Allocate the GPE EventInfo block. There are eight distinct GPEs
939     * per register. Initialization to zeros is sufficient.
940     */
941    GpeEventInfo = ACPI_ALLOCATE_ZEROED (
942                        ((ACPI_SIZE) GpeBlock->RegisterCount *
943                        ACPI_GPE_REGISTER_WIDTH) *
944                        sizeof (ACPI_GPE_EVENT_INFO));
945    if (!GpeEventInfo)
946    {
947        ACPI_ERROR ((AE_INFO,
948            "Could not allocate the GpeEventInfo table"));
949        Status = AE_NO_MEMORY;
950        goto ErrorExit;
951    }
952
953    /* Save the new Info arrays in the GPE block */
954
955    GpeBlock->RegisterInfo = GpeRegisterInfo;
956    GpeBlock->EventInfo    = GpeEventInfo;
957
958    /*
959     * Initialize the GPE Register and Event structures. A goal of these
960     * tables is to hide the fact that there are two separate GPE register
961     * sets in a given GPE hardware block, the status registers occupy the
962     * first half, and the enable registers occupy the second half.
963     */
964    ThisRegister = GpeRegisterInfo;
965    ThisEvent    = GpeEventInfo;
966
967    for (i = 0; i < GpeBlock->RegisterCount; i++)
968    {
969        /* Init the RegisterInfo for this GPE register (8 GPEs) */
970
971        ThisRegister->BaseGpeNumber = (UINT8) (GpeBlock->BlockBaseNumber +
972                                             (i * ACPI_GPE_REGISTER_WIDTH));
973
974        ThisRegister->StatusAddress.Address =
975            GpeBlock->BlockAddress.Address + i;
976
977        ThisRegister->EnableAddress.Address =
978            GpeBlock->BlockAddress.Address + i + GpeBlock->RegisterCount;
979
980        ThisRegister->StatusAddress.SpaceId   = GpeBlock->BlockAddress.SpaceId;
981        ThisRegister->EnableAddress.SpaceId   = GpeBlock->BlockAddress.SpaceId;
982        ThisRegister->StatusAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
983        ThisRegister->EnableAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
984        ThisRegister->StatusAddress.BitOffset = 0;
985        ThisRegister->EnableAddress.BitOffset = 0;
986
987        /* Init the EventInfo for each GPE within this register */
988
989        for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
990        {
991            ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j);
992            ThisEvent->RegisterInfo = ThisRegister;
993            ThisEvent++;
994        }
995
996        /* Disable all GPEs within this register */
997
998        Status = AcpiWrite (0x00, &ThisRegister->EnableAddress);
999        if (ACPI_FAILURE (Status))
1000        {
1001            goto ErrorExit;
1002        }
1003
1004        /* Clear any pending GPE events within this register */
1005
1006        Status = AcpiWrite (0xFF, &ThisRegister->StatusAddress);
1007        if (ACPI_FAILURE (Status))
1008        {
1009            goto ErrorExit;
1010        }
1011
1012        ThisRegister++;
1013    }
1014
1015    return_ACPI_STATUS (AE_OK);
1016
1017
1018ErrorExit:
1019    if (GpeRegisterInfo)
1020    {
1021        ACPI_FREE (GpeRegisterInfo);
1022    }
1023    if (GpeEventInfo)
1024    {
1025        ACPI_FREE (GpeEventInfo);
1026    }
1027
1028    return_ACPI_STATUS (Status);
1029}
1030
1031
1032/*******************************************************************************
1033 *
1034 * FUNCTION:    AcpiEvCreateGpeBlock
1035 *
1036 * PARAMETERS:  GpeDevice           - Handle to the parent GPE block
1037 *              GpeBlockAddress     - Address and SpaceID
1038 *              RegisterCount       - Number of GPE register pairs in the block
1039 *              GpeBlockBaseNumber  - Starting GPE number for the block
1040 *              InterruptNumber     - H/W interrupt for the block
1041 *              ReturnGpeBlock      - Where the new block descriptor is returned
1042 *
1043 * RETURN:      Status
1044 *
1045 * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
1046 *              the block are disabled at exit.
1047 *              Note: Assumes namespace is locked.
1048 *
1049 ******************************************************************************/
1050
1051ACPI_STATUS
1052AcpiEvCreateGpeBlock (
1053    ACPI_NAMESPACE_NODE     *GpeDevice,
1054    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
1055    UINT32                  RegisterCount,
1056    UINT8                   GpeBlockBaseNumber,
1057    UINT32                  InterruptNumber,
1058    ACPI_GPE_BLOCK_INFO     **ReturnGpeBlock)
1059{
1060    ACPI_STATUS             Status;
1061    ACPI_GPE_BLOCK_INFO     *GpeBlock;
1062
1063
1064    ACPI_FUNCTION_TRACE (EvCreateGpeBlock);
1065
1066
1067    if (!RegisterCount)
1068    {
1069        return_ACPI_STATUS (AE_OK);
1070    }
1071
1072    /* Allocate a new GPE block */
1073
1074    GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO));
1075    if (!GpeBlock)
1076    {
1077        return_ACPI_STATUS (AE_NO_MEMORY);
1078    }
1079
1080    /* Initialize the new GPE block */
1081
1082    GpeBlock->Node = GpeDevice;
1083    GpeBlock->RegisterCount = RegisterCount;
1084    GpeBlock->BlockBaseNumber = GpeBlockBaseNumber;
1085
1086    ACPI_MEMCPY (&GpeBlock->BlockAddress, GpeBlockAddress,
1087        sizeof (ACPI_GENERIC_ADDRESS));
1088
1089    /*
1090     * Create the RegisterInfo and EventInfo sub-structures
1091     * Note: disables and clears all GPEs in the block
1092     */
1093    Status = AcpiEvCreateGpeInfoBlocks (GpeBlock);
1094    if (ACPI_FAILURE (Status))
1095    {
1096        ACPI_FREE (GpeBlock);
1097        return_ACPI_STATUS (Status);
1098    }
1099
1100    /* Install the new block in the global lists */
1101
1102    Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber);
1103    if (ACPI_FAILURE (Status))
1104    {
1105        ACPI_FREE (GpeBlock);
1106        return_ACPI_STATUS (Status);
1107    }
1108
1109    /* Find all GPE methods (_Lxx, _Exx) for this block */
1110
1111    Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
1112                ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
1113                AcpiEvSaveMethodInfo, GpeBlock, NULL);
1114
1115    /* Return the new block */
1116
1117    if (ReturnGpeBlock)
1118    {
1119        (*ReturnGpeBlock) = GpeBlock;
1120    }
1121
1122    ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
1123        "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
1124        (UINT32) GpeBlock->BlockBaseNumber,
1125        (UINT32) (GpeBlock->BlockBaseNumber +
1126                ((GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH) -1)),
1127        GpeDevice->Name.Ascii,
1128        GpeBlock->RegisterCount,
1129        InterruptNumber));
1130
1131    /* Update global count of currently available GPEs */
1132
1133    AcpiCurrentGpeCount += RegisterCount * ACPI_GPE_REGISTER_WIDTH;
1134    return_ACPI_STATUS (AE_OK);
1135}
1136
1137
1138/*******************************************************************************
1139 *
1140 * FUNCTION:    AcpiEvInitializeGpeBlock
1141 *
1142 * PARAMETERS:  GpeDevice           - Handle to the parent GPE block
1143 *              GpeBlock            - Gpe Block info
1144 *
1145 * RETURN:      Status
1146 *
1147 * DESCRIPTION: Initialize and enable a GPE block. First find and run any
1148 *              _PRT methods associated with the block, then enable the
1149 *              appropriate GPEs.
1150 *              Note: Assumes namespace is locked.
1151 *
1152 ******************************************************************************/
1153
1154ACPI_STATUS
1155AcpiEvInitializeGpeBlock (
1156    ACPI_NAMESPACE_NODE     *GpeDevice,
1157    ACPI_GPE_BLOCK_INFO     *GpeBlock)
1158{
1159    ACPI_STATUS             Status;
1160    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1161    ACPI_GPE_WALK_INFO      GpeInfo;
1162    UINT32                  WakeGpeCount;
1163    UINT32                  GpeEnabledCount;
1164    UINT32                  i;
1165    UINT32                  j;
1166
1167
1168    ACPI_FUNCTION_TRACE (EvInitializeGpeBlock);
1169
1170
1171    /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
1172
1173    if (!GpeBlock)
1174    {
1175        return_ACPI_STATUS (AE_OK);
1176    }
1177
1178    /*
1179     * Runtime option: Should wake GPEs be enabled at runtime?  The default
1180     * is no, they should only be enabled just as the machine goes to sleep.
1181     */
1182    if (AcpiGbl_LeaveWakeGpesDisabled)
1183    {
1184        /*
1185         * Differentiate runtime vs wake GPEs, via the _PRW control methods.
1186         * Each GPE that has one or more _PRWs that reference it is by
1187         * definition a wake GPE and will not be enabled while the machine
1188         * is running.
1189         */
1190        GpeInfo.GpeBlock = GpeBlock;
1191        GpeInfo.GpeDevice = GpeDevice;
1192
1193        Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1194                    ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
1195                    AcpiEvMatchPrwAndGpe, &GpeInfo, NULL);
1196    }
1197
1198    /*
1199     * Enable all GPEs in this block that have these attributes:
1200     * 1) are "runtime" or "run/wake" GPEs, and
1201     * 2) have a corresponding _Lxx or _Exx method
1202     *
1203     * Any other GPEs within this block must be enabled via the
1204     * AcpiEnableGpe() external interface.
1205     */
1206    WakeGpeCount = 0;
1207    GpeEnabledCount = 0;
1208
1209    for (i = 0; i < GpeBlock->RegisterCount; i++)
1210    {
1211        for (j = 0; j < 8; j++)
1212        {
1213            /* Get the info block for this particular GPE */
1214
1215            GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
1216                ACPI_GPE_REGISTER_WIDTH) + j];
1217
1218            if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
1219                    ACPI_GPE_DISPATCH_METHOD) &&
1220                 (GpeEventInfo->Flags & ACPI_GPE_TYPE_RUNTIME))
1221            {
1222                GpeEnabledCount++;
1223            }
1224
1225            if (GpeEventInfo->Flags & ACPI_GPE_TYPE_WAKE)
1226            {
1227                WakeGpeCount++;
1228            }
1229        }
1230    }
1231
1232    ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
1233        "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
1234        WakeGpeCount, GpeEnabledCount));
1235
1236    /* Enable all valid runtime GPEs found above */
1237
1238    Status = AcpiHwEnableRuntimeGpeBlock (NULL, GpeBlock, NULL);
1239    if (ACPI_FAILURE (Status))
1240    {
1241        ACPI_ERROR ((AE_INFO, "Could not enable GPEs in GpeBlock %p",
1242            GpeBlock));
1243    }
1244
1245    return_ACPI_STATUS (Status);
1246}
1247
1248
1249/*******************************************************************************
1250 *
1251 * FUNCTION:    AcpiEvGpeInitialize
1252 *
1253 * PARAMETERS:  None
1254 *
1255 * RETURN:      Status
1256 *
1257 * DESCRIPTION: Initialize the GPE data structures
1258 *
1259 ******************************************************************************/
1260
1261ACPI_STATUS
1262AcpiEvGpeInitialize (
1263    void)
1264{
1265    UINT32                  RegisterCount0 = 0;
1266    UINT32                  RegisterCount1 = 0;
1267    UINT32                  GpeNumberMax = 0;
1268    ACPI_STATUS             Status;
1269
1270
1271    ACPI_FUNCTION_TRACE (EvGpeInitialize);
1272
1273
1274    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1275    if (ACPI_FAILURE (Status))
1276    {
1277        return_ACPI_STATUS (Status);
1278    }
1279
1280    /*
1281     * Initialize the GPE Block(s) defined in the FADT
1282     *
1283     * Why the GPE register block lengths are divided by 2:  From the ACPI
1284     * Spec, section "General-Purpose Event Registers", we have:
1285     *
1286     * "Each register block contains two registers of equal length
1287     *  GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
1288     *  GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
1289     *  The length of the GPE1_STS and GPE1_EN registers is equal to
1290     *  half the GPE1_LEN. If a generic register block is not supported
1291     *  then its respective block pointer and block length values in the
1292     *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
1293     *  to be the same size."
1294     */
1295
1296    /*
1297     * Determine the maximum GPE number for this machine.
1298     *
1299     * Note: both GPE0 and GPE1 are optional, and either can exist without
1300     * the other.
1301     *
1302     * If EITHER the register length OR the block address are zero, then that
1303     * particular block is not supported.
1304     */
1305    if (AcpiGbl_FADT.Gpe0BlockLength &&
1306        AcpiGbl_FADT.XGpe0Block.Address)
1307    {
1308        /* GPE block 0 exists (has both length and address > 0) */
1309
1310        RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2);
1311
1312        GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1;
1313
1314        /* Install GPE Block 0 */
1315
1316        Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
1317                    &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0,
1318                    AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]);
1319
1320        if (ACPI_FAILURE (Status))
1321        {
1322            ACPI_EXCEPTION ((AE_INFO, Status,
1323                "Could not create GPE Block 0"));
1324        }
1325    }
1326
1327    if (AcpiGbl_FADT.Gpe1BlockLength &&
1328        AcpiGbl_FADT.XGpe1Block.Address)
1329    {
1330        /* GPE block 1 exists (has both length and address > 0) */
1331
1332        RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2);
1333
1334        /* Check for GPE0/GPE1 overlap (if both banks exist) */
1335
1336        if ((RegisterCount0) &&
1337            (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base))
1338        {
1339            ACPI_ERROR ((AE_INFO,
1340                "GPE0 block (GPE 0 to %d) overlaps the GPE1 block "
1341                "(GPE %d to %d) - Ignoring GPE1",
1342                GpeNumberMax, AcpiGbl_FADT.Gpe1Base,
1343                AcpiGbl_FADT.Gpe1Base +
1344                ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
1345
1346            /* Ignore GPE1 block by setting the register count to zero */
1347
1348            RegisterCount1 = 0;
1349        }
1350        else
1351        {
1352            /* Install GPE Block 1 */
1353
1354            Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
1355                        &AcpiGbl_FADT.XGpe1Block, RegisterCount1,
1356                        AcpiGbl_FADT.Gpe1Base,
1357                        AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]);
1358
1359            if (ACPI_FAILURE (Status))
1360            {
1361                ACPI_EXCEPTION ((AE_INFO, Status,
1362                    "Could not create GPE Block 1"));
1363            }
1364
1365            /*
1366             * GPE0 and GPE1 do not have to be contiguous in the GPE number
1367             * space. However, GPE0 always starts at GPE number zero.
1368             */
1369            GpeNumberMax = AcpiGbl_FADT.Gpe1Base +
1370                            ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1);
1371        }
1372    }
1373
1374    /* Exit if there are no GPE registers */
1375
1376    if ((RegisterCount0 + RegisterCount1) == 0)
1377    {
1378        /* GPEs are not required by ACPI, this is OK */
1379
1380        ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
1381            "There are no GPE blocks defined in the FADT\n"));
1382        Status = AE_OK;
1383        goto Cleanup;
1384    }
1385
1386    /* Check for Max GPE number out-of-range */
1387
1388    if (GpeNumberMax > ACPI_GPE_MAX)
1389    {
1390        ACPI_ERROR ((AE_INFO,
1391            "Maximum GPE number from FADT is too large: 0x%X",
1392            GpeNumberMax));
1393        Status = AE_BAD_VALUE;
1394        goto Cleanup;
1395    }
1396
1397Cleanup:
1398    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1399    return_ACPI_STATUS (AE_OK);
1400}
1401
1402
1403