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