Deleted Added
full compact
evgpeblk.c (197104) evgpeblk.c (199337)
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 = AcpiHwWrite (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 = AcpiHwWrite (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,
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 = AcpiHwWrite (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 = AcpiHwWrite (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);
1113 AcpiEvSaveMethodInfo, NULL, 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,
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);
1195 AcpiEvMatchPrwAndGpe, NULL, &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
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