Deleted Added
sdiff udiff text old ( 80062 ) new ( 82367 )
full compact
1/******************************************************************************
2 *
3 * Module Name: evevent - Fixed and General Purpose AcpiEvent
4 * handling and dispatch
5 * $Revision: 46 $
6 *
7 *****************************************************************************/
8
9/******************************************************************************
10 *
11 * 1. Copyright Notice
12 *
13 * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
14 * All rights reserved.
15 *
16 * 2. License
17 *
18 * 2.1. This is your license from Intel Corp. under its intellectual property
19 * rights. You may have additional license terms from the party that provided
20 * you this software, covering your right to use that party's intellectual
21 * property rights.
22 *
23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24 * copy of the source code appearing in this file ("Covered Code") an
25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26 * base code distributed originally by Intel ("Original Intel Code") to copy,
27 * make derivatives, distribute, use and display any portion of the Covered
28 * Code in any form, with the right to sublicense such rights; and
29 *
30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31 * license (with the right to sublicense), under only those claims of Intel
32 * patents that are infringed by the Original Intel Code, to make, use, sell,
33 * offer to sell, and import the Covered Code and derivative works thereof
34 * solely to the minimum extent necessary to exercise the above copyright
35 * license, and in no event shall the patent license extend to any additions
36 * to or modifications of the Original Intel Code. No other license or right
37 * is granted directly or by implication, estoppel or otherwise;
38 *
39 * The above copyright and patent license is granted only if the following
40 * conditions are met:
41 *
42 * 3. Conditions
43 *
44 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45 * Redistribution of source code of any substantial portion of the Covered
46 * Code or modification with rights to further distribute source must include
47 * the above Copyright Notice, the above License, this list of Conditions,
48 * and the following Disclaimer and Export Compliance provision. In addition,
49 * Licensee must cause all Covered Code to which Licensee contributes to
50 * contain a file documenting the changes Licensee made to create that Covered
51 * Code and the date of any change. Licensee must include in that file the
52 * documentation of any changes made by any predecessor Licensee. Licensee
53 * must include a prominent statement that the modification is derived,
54 * directly or indirectly, from Original Intel Code.
55 *
56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57 * Redistribution of source code of any substantial portion of the Covered
58 * Code or modification without rights to further distribute source must
59 * include the following Disclaimer and Export Compliance provision in the
60 * documentation and/or other materials provided with distribution. In
61 * addition, Licensee may not authorize further sublicense of source of any
62 * portion of the Covered Code, and must include terms to the effect that the
63 * license from Licensee to its licensee is limited to the intellectual
64 * property embodied in the software Licensee provides to its licensee, and
65 * not to intellectual property embodied in modifications its licensee may
66 * make.
67 *
68 * 3.3. Redistribution of Executable. Redistribution in executable form of any
69 * substantial portion of the Covered Code or modification must reproduce the
70 * above Copyright Notice, and the following Disclaimer and Export Compliance
71 * provision in the documentation and/or other materials provided with the
72 * distribution.
73 *
74 * 3.4. Intel retains all right, title, and interest in and to the Original
75 * Intel Code.
76 *
77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78 * Intel shall be used in advertising or otherwise to promote the sale, use or
79 * other dealings in products derived from or relating to the Covered Code
80 * without prior written authorization from Intel.
81 *
82 * 4. Disclaimer and Export Compliance
83 *
84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
88 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90 * PARTICULAR PURPOSE.
91 *
92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99 * LIMITED REMEDY.
100 *
101 * 4.3. Licensee shall not export, either directly or indirectly, any of this
102 * software or system incorporating such software without first obtaining any
103 * required license or other approval from the U. S. Department of Commerce or
104 * any other agency or department of the United States Government. In the
105 * event Licensee exports any such software from the United States or
106 * re-exports any such software from a foreign destination, Licensee shall
107 * ensure that the distribution and export/re-export of the software is in
108 * compliance with all laws, regulations, orders, or other restrictions of the
109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110 * any of its subsidiaries will export/re-export any technical data, process,
111 * software, or service, directly or indirectly, to any country for which the
112 * United States government or any agency thereof requires an export license,
113 * other governmental approval, or letter of assurance, without first obtaining
114 * such license, approval or letter.
115 *
116 *****************************************************************************/
117
118#include "acpi.h"
119#include "achware.h"
120#include "acevents.h"
121#include "acnamesp.h"
122
123#define _COMPONENT ACPI_EVENTS
124 MODULE_NAME ("evevent")
125
126
127/*******************************************************************************
128 *
129 * FUNCTION: AcpiEvInitialize
130 *
131 * PARAMETERS: None
132 *
133 * RETURN: Status
134 *
135 * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly
136 * configured, disables SCI event sources, installs the SCI
137 * handler
138 *
139 ******************************************************************************/
140
141ACPI_STATUS
142AcpiEvInitialize (
143 void)
144{
145 ACPI_STATUS Status;
146
147
148 FUNCTION_TRACE ("EvInitialize");
149
150
151 /* Make sure we have ACPI tables */
152
153 if (!AcpiGbl_DSDT)
154 {
155 DEBUG_PRINTP (ACPI_WARN, ("No ACPI tables present!\n"));
156 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
157 }
158
159
160 /* Make sure the BIOS supports ACPI mode */
161
162 if (SYS_MODE_LEGACY == AcpiHwGetModeCapabilities())
163 {
164 DEBUG_PRINTP (ACPI_WARN, ("ACPI Mode is not supported!\n"));
165 return_ACPI_STATUS (AE_ERROR);
166 }
167
168
169 AcpiGbl_OriginalMode = AcpiHwGetMode();
170
171 /*
172 * Initialize the Fixed and General Purpose AcpiEvents prior. This is
173 * done prior to enabling SCIs to prevent interrupts from occuring
174 * before handers are installed.
175 */
176
177 Status = AcpiEvFixedEventInitialize ();
178 if (ACPI_FAILURE (Status))
179 {
180 DEBUG_PRINTP (ACPI_FATAL, ("Unable to initialize fixed events.\n"));
181 return_ACPI_STATUS (Status);
182 }
183
184 Status = AcpiEvGpeInitialize ();
185 if (ACPI_FAILURE (Status))
186 {
187 DEBUG_PRINTP (ACPI_FATAL, ("Unable to initialize general purpose events.\n"));
188 return_ACPI_STATUS (Status);
189 }
190
191 /* Install the SCI handler */
192
193 Status = AcpiEvInstallSciHandler ();
194 if (ACPI_FAILURE (Status))
195 {
196 DEBUG_PRINTP (ACPI_FATAL, ("Unable to install System Control Interrupt Handler\n"));
197 return_ACPI_STATUS (Status);
198 }
199
200
201 /* Install handlers for control method GPE handlers (_Lxx, _Exx) */
202
203 Status = AcpiEvInitGpeControlMethods ();
204 if (ACPI_FAILURE (Status))
205 {
206 DEBUG_PRINTP (ACPI_FATAL, ("Unable to initialize Gpe control methods\n"));
207 return_ACPI_STATUS (Status);
208 }
209
210 /* Install the handler for the Global Lock */
211
212 Status = AcpiEvInitGlobalLockHandler ();
213 if (ACPI_FAILURE (Status))
214 {
215 DEBUG_PRINTP (ACPI_FATAL, ("Unable to initialize Global Lock handler\n"));
216 return_ACPI_STATUS (Status);
217 }
218
219
220 return_ACPI_STATUS (Status);
221}
222
223
224/*******************************************************************************
225 *
226 * FUNCTION: AcpiEvFixedEventInitialize
227 *
228 * PARAMETERS: None
229 *
230 * RETURN: Status
231 *
232 * DESCRIPTION: Initialize the Fixed AcpiEvent data structures
233 *
234 ******************************************************************************/
235
236ACPI_STATUS
237AcpiEvFixedEventInitialize(void)
238{
239 int i = 0;
240
241 /* Initialize the structure that keeps track of fixed event handlers */
242
243 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
244 {
245 AcpiGbl_FixedEventHandlers[i].Handler = NULL;
246 AcpiGbl_FixedEventHandlers[i].Context = NULL;
247 }
248
249 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0);
250 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0);
251 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0);
252 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0);
253 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0);
254
255 return (AE_OK);
256}
257
258
259/*******************************************************************************
260 *
261 * FUNCTION: AcpiEvFixedEventDetect
262 *
263 * PARAMETERS: None
264 *
265 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
266 *
267 * DESCRIPTION: Checks the PM status register for fixed events
268 *
269 ******************************************************************************/
270
271UINT32
272AcpiEvFixedEventDetect(void)
273{
274 UINT32 IntStatus = INTERRUPT_NOT_HANDLED;
275 UINT32 StatusRegister;
276 UINT32 EnableRegister;
277
278 /*
279 * Read the fixed feature status and enable registers, as all the cases
280 * depend on their values.
281 */
282
283 StatusRegister = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
284 EnableRegister = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
285
286 DEBUG_PRINT (TRACE_INTERRUPTS,
287 ("Fixed AcpiEvent Block: Enable %08X Status %08X\n",
288 EnableRegister, StatusRegister));
289
290
291 /* power management timer roll over */
292
293 if ((StatusRegister & ACPI_STATUS_PMTIMER) &&
294 (EnableRegister & ACPI_ENABLE_PMTIMER))
295 {
296 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_PMTIMER);
297 }
298
299 /* global event (BIOS wants the global lock) */
300
301 if ((StatusRegister & ACPI_STATUS_GLOBAL) &&
302 (EnableRegister & ACPI_ENABLE_GLOBAL))
303 {
304 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_GLOBAL);
305 }
306
307 /* power button event */
308
309 if ((StatusRegister & ACPI_STATUS_POWER_BUTTON) &&
310 (EnableRegister & ACPI_ENABLE_POWER_BUTTON))
311 {
312 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_POWER_BUTTON);
313 }
314
315 /* sleep button event */
316
317 if ((StatusRegister & ACPI_STATUS_SLEEP_BUTTON) &&
318 (EnableRegister & ACPI_ENABLE_SLEEP_BUTTON))
319 {
320 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_SLEEP_BUTTON);
321 }
322
323 return (IntStatus);
324}
325
326
327/*******************************************************************************
328 *
329 * FUNCTION: AcpiEvFixedEventDispatch
330 *
331 * PARAMETERS: Event - Event type
332 *
333 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
334 *
335 * DESCRIPTION: Clears the status bit for the requested event, calls the
336 * handler that previously registered for the event.
337 *
338 ******************************************************************************/
339
340UINT32
341AcpiEvFixedEventDispatch (
342 UINT32 Event)
343{
344 UINT32 RegisterId;
345
346 /* Clear the status bit */
347
348 switch (Event)
349 {
350 case ACPI_EVENT_PMTIMER:
351 RegisterId = TMR_STS;
352 break;
353
354 case ACPI_EVENT_GLOBAL:
355 RegisterId = GBL_STS;
356 break;
357
358 case ACPI_EVENT_POWER_BUTTON:
359 RegisterId = PWRBTN_STS;
360 break;
361
362 case ACPI_EVENT_SLEEP_BUTTON:
363 RegisterId = SLPBTN_STS;
364 break;
365
366 case ACPI_EVENT_RTC:
367 RegisterId = RTC_STS;
368 break;
369
370 default:
371 return 0;
372 break;
373 }
374
375 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, RegisterId, 1);
376
377 /*
378 * Make sure we've got a handler. If not, report an error.
379 * The event is disabled to prevent further interrupts.
380 */
381 if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler)
382 {
383 RegisterId = (PM1_EN | REGISTER_BIT_ID(RegisterId));
384
385 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,
386 RegisterId, 0);
387
388 REPORT_ERROR (
389 ("EvGpeDispatch: No installed handler for fixed event [%08X]\n",
390 Event));
391
392 return (INTERRUPT_NOT_HANDLED);
393 }
394
395 /* Invoke the handler */
396
397 return ((AcpiGbl_FixedEventHandlers[Event].Handler)(
398 AcpiGbl_FixedEventHandlers[Event].Context));
399}
400
401
402/*******************************************************************************
403 *
404 * FUNCTION: AcpiEvGpeInitialize
405 *
406 * PARAMETERS: None
407 *
408 * RETURN: Status
409 *
410 * DESCRIPTION: Initialize the GPE data structures
411 *
412 ******************************************************************************/
413
414ACPI_STATUS
415AcpiEvGpeInitialize (void)
416{
417 UINT32 i;
418 UINT32 j;
419 UINT32 RegisterIndex;
420 UINT32 GpeNumber;
421 UINT16 Gpe0RegisterCount;
422 UINT16 Gpe1RegisterCount;
423
424
425 FUNCTION_TRACE ("EvGpeInitialize");
426
427 /*
428 * Set up various GPE counts
429 *
430 * You may ask,why are the GPE register block lengths divided by 2?
431 * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event
432 * Registers, we have,
433 *
434 * "Each register block contains two registers of equal length
435 * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
436 * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
437 * The length of the GPE1_STS and GPE1_EN registers is equal to
438 * half the GPE1_LEN. If a generic register block is not supported
439 * then its respective block pointer and block length values in the
440 * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
441 * to be the same size."
442 */
443
444 Gpe0RegisterCount = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
445 Gpe1RegisterCount = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
446 AcpiGbl_GpeRegisterCount = Gpe0RegisterCount + Gpe1RegisterCount;
447
448 if (!AcpiGbl_GpeRegisterCount)
449 {
450 REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
451 return_ACPI_STATUS (AE_OK);
452 }
453
454 /*
455 * Allocate the Gpe information block
456 */
457
458 AcpiGbl_GpeRegisters = ACPI_MEM_CALLOCATE (AcpiGbl_GpeRegisterCount *
459 sizeof (ACPI_GPE_REGISTERS));
460 if (!AcpiGbl_GpeRegisters)
461 {
462 DEBUG_PRINTP (ACPI_ERROR,
463 ("Could not allocate the GpeRegisters block\n"));
464 return_ACPI_STATUS (AE_NO_MEMORY);
465 }
466
467 /*
468 * Allocate the Gpe dispatch handler block
469 * There are eight distinct GP events per register.
470 * Initialization to zeros is sufficient
471 */
472
473 AcpiGbl_GpeInfo = ACPI_MEM_CALLOCATE (MUL_8 (AcpiGbl_GpeRegisterCount) *
474 sizeof (ACPI_GPE_LEVEL_INFO));
475 if (!AcpiGbl_GpeInfo)
476 {
477 ACPI_MEM_FREE (AcpiGbl_GpeRegisters);
478 DEBUG_PRINTP (ACPI_ERROR, ("Could not allocate the GpeInfo block\n"));
479 return_ACPI_STATUS (AE_NO_MEMORY);
480 }
481
482 /* Set the Gpe validation table to GPE_INVALID */
483
484 MEMSET (AcpiGbl_GpeValid, (int) ACPI_GPE_INVALID, ACPI_NUM_GPE);
485
486 /*
487 * Initialize the Gpe information and validation blocks. A goal of these
488 * blocks is to hide the fact that there are two separate GPE register sets
489 * In a given block, the status registers occupy the first half, and
490 * the enable registers occupy the second half.
491 */
492
493 /* GPE Block 0 */
494
495 RegisterIndex = 0;
496
497 for (i = 0; i < Gpe0RegisterCount; i++)
498 {
499 AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr =
500 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + i);
501
502 AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr =
503 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + i + Gpe0RegisterCount);
504
505 AcpiGbl_GpeRegisters[RegisterIndex].GpeBase = (UINT8) MUL_8 (i);
506
507 for (j = 0; j < 8; j++)
508 {
509 GpeNumber = AcpiGbl_GpeRegisters[RegisterIndex].GpeBase + j;
510 AcpiGbl_GpeValid[GpeNumber] = (UINT8) RegisterIndex;
511 }
512
513 /*
514 * Clear the status/enable registers. Note that status registers
515 * are cleared by writing a '1', while enable registers are cleared
516 * by writing a '0'.
517 */
518 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr, 0x00, 8);
519 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr, 0xFF, 8);
520
521 RegisterIndex++;
522 }
523
524 /* GPE Block 1 */
525
526 for (i = 0; i < Gpe1RegisterCount; i++)
527 {
528 AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr =
529 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + i);
530
531 AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr =
532 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + i + Gpe1RegisterCount);
533
534 AcpiGbl_GpeRegisters[RegisterIndex].GpeBase =
535 (UINT8) (AcpiGbl_FADT->Gpe1Base + MUL_8 (i));
536
537 for (j = 0; j < 8; j++)
538 {
539 GpeNumber = AcpiGbl_GpeRegisters[RegisterIndex].GpeBase + j;
540 AcpiGbl_GpeValid[GpeNumber] = (UINT8) RegisterIndex;
541 }
542
543 /*
544 * Clear the status/enable registers. Note that status registers
545 * are cleared by writing a '1', while enable registers are cleared
546 * by writing a '0'.
547 */
548 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr, 0x00, 8);
549 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr, 0xFF, 8);
550
551 RegisterIndex++;
552 }
553
554 DEBUG_PRINTP (ACPI_INFO, ("GPE registers: %X@%p (Blk0) %X@%p (Blk1)\n",
555 Gpe0RegisterCount, AcpiGbl_FADT->XGpe0Blk.Address, Gpe1RegisterCount,
556 AcpiGbl_FADT->XGpe1Blk.Address));
557
558 return_ACPI_STATUS (AE_OK);
559}
560
561
562/*******************************************************************************
563 *
564 * FUNCTION: AcpiEvSaveMethodInfo
565 *
566 * PARAMETERS: None
567 *
568 * RETURN: None
569 *
570 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
571 * control method under the _GPE portion of the namespace.
572 * Extract the name and GPE type from the object, saving this
573 * information for quick lookup during GPE dispatch
574 *
575 * The name of each GPE control method is of the form:
576 * "_Lnn" or "_Enn"
577 * Where:
578 * L - means that the GPE is level triggered
579 * E - means that the GPE is edge triggered
580 * nn - is the GPE number
581 *
582 ******************************************************************************/
583
584static ACPI_STATUS
585AcpiEvSaveMethodInfo (
586 ACPI_HANDLE ObjHandle,
587 UINT32 Level,
588 void *ObjDesc,
589 void **ReturnValue)
590{
591 UINT32 GpeNumber;
592 NATIVE_CHAR Name[ACPI_NAME_SIZE + 1];
593 UINT8 Type;
594
595
596 PROC_NAME ("EvSaveMethodInfo");
597
598
599 /* Extract the name from the object and convert to a string */
600
601 MOVE_UNALIGNED32_TO_32 (Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name);
602 Name[ACPI_NAME_SIZE] = 0;
603
604 /*
605 * Edge/Level determination is based on the 2nd INT8 of the method name
606 */
607 if (Name[1] == 'L')
608 {
609 Type = ACPI_EVENT_LEVEL_TRIGGERED;
610 }
611 else if (Name[1] == 'E')
612 {
613 Type = ACPI_EVENT_EDGE_TRIGGERED;
614 }
615 else
616 {
617 /* Unknown method type, just ignore it! */
618
619 DEBUG_PRINTP (ACPI_ERROR,
620 ("Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
621 Name));
622 return (AE_OK);
623 }
624
625 /* Convert the last two characters of the name to the Gpe Number */
626
627 GpeNumber = STRTOUL (&Name[2], NULL, 16);
628 if (GpeNumber == ACPI_UINT32_MAX)
629 {
630 /* Conversion failed; invalid method, just ignore it */
631
632 DEBUG_PRINTP (ACPI_ERROR,
633 ("Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n",
634 Name));
635 return (AE_OK);
636 }
637
638 /* Ensure that we have a valid GPE number */
639
640 if (AcpiGbl_GpeValid[GpeNumber] == ACPI_GPE_INVALID)
641 {
642 /* Not valid, all we can do here is ignore it */
643
644 return (AE_OK);
645 }
646
647 /*
648 * Now we can add this information to the GpeInfo block
649 * for use during dispatch of this GPE.
650 */
651
652 AcpiGbl_GpeInfo [GpeNumber].Type = Type;
653 AcpiGbl_GpeInfo [GpeNumber].MethodHandle = ObjHandle;
654
655
656 /*
657 * Enable the GPE (SCIs should be disabled at this point)
658 */
659
660 AcpiHwEnableGpe (GpeNumber);
661
662 DEBUG_PRINTP (ACPI_INFO, ("Registered GPE method %s as GPE number %X\n",
663 Name, GpeNumber));
664 return (AE_OK);
665}
666
667
668/*******************************************************************************
669 *
670 * FUNCTION: AcpiEvInitGpeControlMethods
671 *
672 * PARAMETERS: None
673 *
674 * RETURN: None
675 *
676 * DESCRIPTION: Obtain the control methods associated with the GPEs.
677 *
678 * NOTE: Must be called AFTER namespace initialization!
679 *
680 ******************************************************************************/
681
682ACPI_STATUS
683AcpiEvInitGpeControlMethods (void)
684{
685 ACPI_STATUS Status;
686
687
688 FUNCTION_TRACE ("EvInitGpeControlMethods");
689
690
691 /* Get a permanent handle to the _GPE object */
692
693 Status = AcpiGetHandle (NULL, "\\_GPE", &AcpiGbl_GpeObjHandle);
694 if (ACPI_FAILURE (Status))
695 {
696 return_ACPI_STATUS (Status);
697 }
698
699 /* Traverse the namespace under \_GPE to find all methods there */
700
701 Status = AcpiWalkNamespace (ACPI_TYPE_METHOD, AcpiGbl_GpeObjHandle,
702 ACPI_UINT32_MAX, AcpiEvSaveMethodInfo,
703 NULL, NULL);
704
705 return_ACPI_STATUS (Status);
706}
707
708
709/*******************************************************************************
710 *
711 * FUNCTION: AcpiEvGpeDetect
712 *
713 * PARAMETERS: None
714 *
715 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
716 *
717 * DESCRIPTION: Detect if any GP events have occurred
718 *
719 ******************************************************************************/
720
721UINT32
722AcpiEvGpeDetect (void)
723{
724 UINT32 IntStatus = INTERRUPT_NOT_HANDLED;
725 UINT32 i;
726 UINT32 j;
727 UINT8 EnabledStatusByte;
728 UINT8 BitMask;
729
730
731 /*
732 * Read all of the 8-bit GPE status and enable registers
733 * in both of the register blocks, saving all of it.
734 * Find all currently active GP events.
735 */
736 for (i = 0; i < AcpiGbl_GpeRegisterCount; i++)
737 {
738 AcpiOsReadPort (AcpiGbl_GpeRegisters[i].StatusAddr,
739 &AcpiGbl_GpeRegisters[i].Status, 8);
740
741 AcpiOsReadPort (AcpiGbl_GpeRegisters[i].EnableAddr,
742 &AcpiGbl_GpeRegisters[i].Enable, 8);
743
744 DEBUG_PRINT (TRACE_INTERRUPTS,
745 ("GPE block at %X - Enable %08X Status %08X\n",
746 AcpiGbl_GpeRegisters[i].EnableAddr,
747 AcpiGbl_GpeRegisters[i].Status,
748 AcpiGbl_GpeRegisters[i].Enable));
749
750 /* First check if there is anything active at all in this register */
751
752 EnabledStatusByte = (UINT8) (AcpiGbl_GpeRegisters[i].Status &
753 AcpiGbl_GpeRegisters[i].Enable);
754
755 if (!EnabledStatusByte)
756 {
757 /* No active GPEs in this register, move on */
758
759 continue;
760 }
761
762 /* Now look at the individual GPEs in this byte register */
763
764 for (j = 0, BitMask = 1; j < 8; j++, BitMask <<= 1)
765 {
766 /* Examine one GPE bit */
767
768 if (EnabledStatusByte & BitMask)
769 {
770 /*
771 * Found an active GPE. Dispatch the event to a handler
772 * or method.
773 */
774 IntStatus |= AcpiEvGpeDispatch (
775 AcpiGbl_GpeRegisters[i].GpeBase + j);
776 }
777 }
778 }
779
780 return (IntStatus);
781}
782
783
784/*******************************************************************************
785 *
786 * FUNCTION: AcpiEvAsynchExecuteGpeMethod
787 *
788 * PARAMETERS: GpeNumber - The 0-based Gpe number
789 *
790 * RETURN: None
791 *
792 * DESCRIPTION: Perform the actual execution of a GPE control method. This
793 * function is called from an invocation of AcpiOsQueueForExecution
794 * (and therefore does NOT execute at interrupt level) so that
795 * the control method itself is not executed in the context of
796 * the SCI interrupt handler.
797 *
798 ******************************************************************************/
799
800static void
801AcpiEvAsynchExecuteGpeMethod (
802 void *Context)
803{
804 UINT32 GpeNumber = (UINT32) Context;
805 ACPI_GPE_LEVEL_INFO GpeInfo;
806
807
808 FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
809
810 /*
811 * Take a snapshot of the GPE info for this level
812 */
813 AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
814 GpeInfo = AcpiGbl_GpeInfo [GpeNumber];
815 AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
816
817 /*
818 * Method Handler (_Lxx, _Exx):
819 * ----------------------------
820 * Evaluate the _Lxx/_Exx control method that corresponds to this GPE.
821 */
822 if (GpeInfo.MethodHandle)
823 {
824 AcpiNsEvaluateByHandle (GpeInfo.MethodHandle, NULL, NULL);
825 }
826
827 /*
828 * Level-Triggered?
829 * ----------------
830 * If level-triggered we clear the GPE status bit after handling the event.
831 */
832 if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
833 {
834 AcpiHwClearGpe (GpeNumber);
835 }
836
837 /*
838 * Enable the GPE.
839 */
840 AcpiHwEnableGpe (GpeNumber);
841
842 return_VOID;
843}
844
845
846/*******************************************************************************
847 *
848 * FUNCTION: AcpiEvGpeDispatch
849 *
850 * PARAMETERS: GpeNumber - The 0-based Gpe number
851 *
852 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
853 *
854 * DESCRIPTION: Handle and dispatch a General Purpose AcpiEvent.
855 * Clears the status bit for the requested event.
856 *
857 * TBD: [Investigate] is this still valid or necessary:
858 * The Gpe handler differs from the fixed events in that it clears the enable
859 * bit rather than the status bit to clear the interrupt. This allows
860 * software outside of interrupt context to determine what caused the SCI and
861 * dispatch the correct AML.
862 *
863 ******************************************************************************/
864
865UINT32
866AcpiEvGpeDispatch (
867 UINT32 GpeNumber)
868{
869 ACPI_GPE_LEVEL_INFO GpeInfo;
870
871 FUNCTION_TRACE ("EvGpeDispatch");
872
873
874 /*
875 * Valid GPE number?
876 */
877 if (AcpiGbl_GpeValid[GpeNumber] == ACPI_GPE_INVALID)
878 {
879 DEBUG_PRINTP (ACPI_ERROR, ("Invalid GPE bit [%X].\n", GpeNumber));
880 return_VALUE (INTERRUPT_NOT_HANDLED);
881 }
882
883 /*
884 * Disable the GPE.
885 */
886 AcpiHwDisableGpe (GpeNumber);
887
888 GpeInfo = AcpiGbl_GpeInfo [GpeNumber];
889
890 /*
891 * Edge-Triggered?
892 * ---------------
893 * If edge-triggered, clear the GPE status bit now. Note that
894 * level-triggered events are cleared after the GPE is serviced.
895 */
896 if (GpeInfo.Type & ACPI_EVENT_EDGE_TRIGGERED)
897 {
898 AcpiHwClearGpe (GpeNumber);
899 }
900 /*
901 * Function Handler (e.g. EC)?
902 */
903 if (GpeInfo.Handler)
904 {
905 /* Invoke function handler (at interrupt level). */
906
907 GpeInfo.Handler (GpeInfo.Context);
908
909 /* Level-Triggered? */
910
911 if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
912 {
913 AcpiHwClearGpe (GpeNumber);
914 }
915
916 /* Enable GPE */
917
918 AcpiHwEnableGpe (GpeNumber);
919 }
920
921 /*
922 * Method Handler (e.g. _Exx/_Lxx)?
923 */
924 else if (GpeInfo.MethodHandle)
925 {
926 if (ACPI_FAILURE(AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
927 AcpiEvAsynchExecuteGpeMethod, (void*) GpeNumber)))
928 {
929 /*
930 * Shoudn't occur, but if it does report an error. Note that
931 * the GPE will remain disabled until the ACPI Core Subsystem
932 * is restarted, or the handler is removed/reinstalled.
933 */
934 REPORT_ERROR (("AcpiEvGpeDispatch: Unable to queue handler for GPE bit [%X]\n", GpeNumber));
935 }
936 }
937
938 /*
939 * No Handler? Report an error and leave the GPE disabled.
940 */
941 else
942 {
943 REPORT_ERROR (("AcpiEvGpeDispatch: No installed handler for GPE [%X]\n", GpeNumber));
944
945 /* Level-Triggered? */
946
947 if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
948 {
949 AcpiHwClearGpe (GpeNumber);
950 }
951 }
952
953 return_VALUE (INTERRUPT_HANDLED);
954}