Deleted Added
full compact
1/******************************************************************************
2 *
3 * Module Name: evevent - Fixed and General Purpose AcpiEvent
4 * handling and dispatch
5 * $Revision: 46 $
5 * $Revision: 47 $
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"));
155 ACPI_DEBUG_PRINT ((ACPI_DB_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"));
164 ACPI_DEBUG_PRINT ((ACPI_DB_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"));
180 ACPI_DEBUG_PRINT ((ACPI_DB_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"));
187 ACPI_DEBUG_PRINT ((ACPI_DB_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"));
196 ACPI_DEBUG_PRINT ((ACPI_DB_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"));
206 ACPI_DEBUG_PRINT ((ACPI_DB_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"));
215 ACPI_DEBUG_PRINT ((ACPI_DB_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)
272AcpiEvFixedEventDetect (void)
273{
274 UINT32 IntStatus = INTERRUPT_NOT_HANDLED;
275 UINT32 StatusRegister;
276 UINT32 EnableRegister;
277
278 PROC_NAME ("AcpiEvFixedEventDetect");
279
280
281 /*
282 * Read the fixed feature status and enable registers, as all the cases
283 * depend on their values.
284 */
285
286 StatusRegister = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
287 EnableRegister = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
288
286 DEBUG_PRINT (TRACE_INTERRUPTS,
287 ("Fixed AcpiEvent Block: Enable %08X Status %08X\n",
289 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
290 "Fixed AcpiEvent Block: Enable %08X Status %08X\n",
291 EnableRegister, StatusRegister));
292
293
294 /* power management timer roll over */
295
296 if ((StatusRegister & ACPI_STATUS_PMTIMER) &&
297 (EnableRegister & ACPI_ENABLE_PMTIMER))
298 {
299 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_PMTIMER);
300 }
301
302 /* global event (BIOS wants the global lock) */
303
304 if ((StatusRegister & ACPI_STATUS_GLOBAL) &&
305 (EnableRegister & ACPI_ENABLE_GLOBAL))
306 {
307 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_GLOBAL);
308 }
309
310 /* power button event */
311
312 if ((StatusRegister & ACPI_STATUS_POWER_BUTTON) &&
313 (EnableRegister & ACPI_ENABLE_POWER_BUTTON))
314 {
315 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_POWER_BUTTON);
316 }
317
318 /* sleep button event */
319
320 if ((StatusRegister & ACPI_STATUS_SLEEP_BUTTON) &&
321 (EnableRegister & ACPI_ENABLE_SLEEP_BUTTON))
322 {
323 IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_SLEEP_BUTTON);
324 }
325
326 return (IntStatus);
327}
328
329
330/*******************************************************************************
331 *
332 * FUNCTION: AcpiEvFixedEventDispatch
333 *
334 * PARAMETERS: Event - Event type
335 *
336 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
337 *
338 * DESCRIPTION: Clears the status bit for the requested event, calls the
339 * handler that previously registered for the event.
340 *
341 ******************************************************************************/
342
343UINT32
344AcpiEvFixedEventDispatch (
345 UINT32 Event)
346{
347 UINT32 RegisterId;
348
349 /* Clear the status bit */
350
351 switch (Event)
352 {
353 case ACPI_EVENT_PMTIMER:
354 RegisterId = TMR_STS;
355 break;
356
357 case ACPI_EVENT_GLOBAL:
358 RegisterId = GBL_STS;
359 break;
360
361 case ACPI_EVENT_POWER_BUTTON:
362 RegisterId = PWRBTN_STS;
363 break;
364
365 case ACPI_EVENT_SLEEP_BUTTON:
366 RegisterId = SLPBTN_STS;
367 break;
368
369 case ACPI_EVENT_RTC:
370 RegisterId = RTC_STS;
371 break;
372
373 default:
374 return 0;
375 break;
376 }
377
378 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, RegisterId, 1);
379
380 /*
381 * Make sure we've got a handler. If not, report an error.
382 * The event is disabled to prevent further interrupts.
383 */
384 if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler)
385 {
386 RegisterId = (PM1_EN | REGISTER_BIT_ID(RegisterId));
387
388 AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,
389 RegisterId, 0);
390
391 REPORT_ERROR (
392 ("EvGpeDispatch: No installed handler for fixed event [%08X]\n",
393 Event));
394
395 return (INTERRUPT_NOT_HANDLED);
396 }
397
398 /* Invoke the handler */
399
400 return ((AcpiGbl_FixedEventHandlers[Event].Handler)(
401 AcpiGbl_FixedEventHandlers[Event].Context));
402}
403
404
405/*******************************************************************************
406 *
407 * FUNCTION: AcpiEvGpeInitialize
408 *
409 * PARAMETERS: None
410 *
411 * RETURN: Status
412 *
413 * DESCRIPTION: Initialize the GPE data structures
414 *
415 ******************************************************************************/
416
417ACPI_STATUS
418AcpiEvGpeInitialize (void)
419{
420 UINT32 i;
421 UINT32 j;
422 UINT32 RegisterIndex;
423 UINT32 GpeNumber;
424 UINT16 Gpe0RegisterCount;
425 UINT16 Gpe1RegisterCount;
426
427
428 FUNCTION_TRACE ("EvGpeInitialize");
429
430 /*
431 * Set up various GPE counts
432 *
433 * You may ask,why are the GPE register block lengths divided by 2?
434 * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event
435 * Registers, we have,
436 *
437 * "Each register block contains two registers of equal length
438 * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
439 * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
440 * The length of the GPE1_STS and GPE1_EN registers is equal to
441 * half the GPE1_LEN. If a generic register block is not supported
442 * then its respective block pointer and block length values in the
443 * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
444 * to be the same size."
445 */
446
447 Gpe0RegisterCount = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
448 Gpe1RegisterCount = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
449 AcpiGbl_GpeRegisterCount = Gpe0RegisterCount + Gpe1RegisterCount;
450
451 if (!AcpiGbl_GpeRegisterCount)
452 {
453 REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
454 return_ACPI_STATUS (AE_OK);
455 }
456
457 /*
458 * Allocate the Gpe information block
459 */
460
461 AcpiGbl_GpeRegisters = ACPI_MEM_CALLOCATE (AcpiGbl_GpeRegisterCount *
462 sizeof (ACPI_GPE_REGISTERS));
463 if (!AcpiGbl_GpeRegisters)
464 {
462 DEBUG_PRINTP (ACPI_ERROR,
463 ("Could not allocate the GpeRegisters block\n"));
465 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
466 "Could not allocate the GpeRegisters block\n"));
467 return_ACPI_STATUS (AE_NO_MEMORY);
468 }
469
470 /*
471 * Allocate the Gpe dispatch handler block
472 * There are eight distinct GP events per register.
473 * Initialization to zeros is sufficient
474 */
475
476 AcpiGbl_GpeInfo = ACPI_MEM_CALLOCATE (MUL_8 (AcpiGbl_GpeRegisterCount) *
477 sizeof (ACPI_GPE_LEVEL_INFO));
478 if (!AcpiGbl_GpeInfo)
479 {
480 ACPI_MEM_FREE (AcpiGbl_GpeRegisters);
478 DEBUG_PRINTP (ACPI_ERROR, ("Could not allocate the GpeInfo block\n"));
481 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the GpeInfo block\n"));
482 return_ACPI_STATUS (AE_NO_MEMORY);
483 }
484
485 /* Set the Gpe validation table to GPE_INVALID */
486
487 MEMSET (AcpiGbl_GpeValid, (int) ACPI_GPE_INVALID, ACPI_NUM_GPE);
488
489 /*
490 * Initialize the Gpe information and validation blocks. A goal of these
491 * blocks is to hide the fact that there are two separate GPE register sets
492 * In a given block, the status registers occupy the first half, and
493 * the enable registers occupy the second half.
494 */
495
496 /* GPE Block 0 */
497
498 RegisterIndex = 0;
499
500 for (i = 0; i < Gpe0RegisterCount; i++)
501 {
502 AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr =
503 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + i);
504
505 AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr =
506 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + i + Gpe0RegisterCount);
507
508 AcpiGbl_GpeRegisters[RegisterIndex].GpeBase = (UINT8) MUL_8 (i);
509
510 for (j = 0; j < 8; j++)
511 {
512 GpeNumber = AcpiGbl_GpeRegisters[RegisterIndex].GpeBase + j;
513 AcpiGbl_GpeValid[GpeNumber] = (UINT8) RegisterIndex;
514 }
515
516 /*
517 * Clear the status/enable registers. Note that status registers
518 * are cleared by writing a '1', while enable registers are cleared
519 * by writing a '0'.
520 */
521 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr, 0x00, 8);
522 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr, 0xFF, 8);
523
524 RegisterIndex++;
525 }
526
527 /* GPE Block 1 */
528
529 for (i = 0; i < Gpe1RegisterCount; i++)
530 {
531 AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr =
532 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + i);
533
534 AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr =
535 (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + i + Gpe1RegisterCount);
536
537 AcpiGbl_GpeRegisters[RegisterIndex].GpeBase =
538 (UINT8) (AcpiGbl_FADT->Gpe1Base + MUL_8 (i));
539
540 for (j = 0; j < 8; j++)
541 {
542 GpeNumber = AcpiGbl_GpeRegisters[RegisterIndex].GpeBase + j;
543 AcpiGbl_GpeValid[GpeNumber] = (UINT8) RegisterIndex;
544 }
545
546 /*
547 * Clear the status/enable registers. Note that status registers
548 * are cleared by writing a '1', while enable registers are cleared
549 * by writing a '0'.
550 */
551 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr, 0x00, 8);
552 AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr, 0xFF, 8);
553
554 RegisterIndex++;
555 }
556
554 DEBUG_PRINTP (ACPI_INFO, ("GPE registers: %X@%p (Blk0) %X@%p (Blk1)\n",
557 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE registers: %X@%p (Blk0) %X@%p (Blk1)\n",
558 Gpe0RegisterCount, AcpiGbl_FADT->XGpe0Blk.Address, Gpe1RegisterCount,
559 AcpiGbl_FADT->XGpe1Blk.Address));
560
561 return_ACPI_STATUS (AE_OK);
562}
563
564
565/*******************************************************************************
566 *
567 * FUNCTION: AcpiEvSaveMethodInfo
568 *
569 * PARAMETERS: None
570 *
571 * RETURN: None
572 *
573 * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
574 * control method under the _GPE portion of the namespace.
575 * Extract the name and GPE type from the object, saving this
576 * information for quick lookup during GPE dispatch
577 *
578 * The name of each GPE control method is of the form:
579 * "_Lnn" or "_Enn"
580 * Where:
581 * L - means that the GPE is level triggered
582 * E - means that the GPE is edge triggered
583 * nn - is the GPE number
584 *
585 ******************************************************************************/
586
587static ACPI_STATUS
588AcpiEvSaveMethodInfo (
589 ACPI_HANDLE ObjHandle,
590 UINT32 Level,
591 void *ObjDesc,
592 void **ReturnValue)
593{
594 UINT32 GpeNumber;
595 NATIVE_CHAR Name[ACPI_NAME_SIZE + 1];
596 UINT8 Type;
597
598
599 PROC_NAME ("EvSaveMethodInfo");
600
601
602 /* Extract the name from the object and convert to a string */
603
604 MOVE_UNALIGNED32_TO_32 (Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name);
605 Name[ACPI_NAME_SIZE] = 0;
606
607 /*
608 * Edge/Level determination is based on the 2nd INT8 of the method name
609 */
610 if (Name[1] == 'L')
611 {
612 Type = ACPI_EVENT_LEVEL_TRIGGERED;
613 }
614 else if (Name[1] == 'E')
615 {
616 Type = ACPI_EVENT_EDGE_TRIGGERED;
617 }
618 else
619 {
620 /* Unknown method type, just ignore it! */
621
619 DEBUG_PRINTP (ACPI_ERROR,
620 ("Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
622 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
623 "Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
624 Name));
625 return (AE_OK);
626 }
627
628 /* Convert the last two characters of the name to the Gpe Number */
629
630 GpeNumber = STRTOUL (&Name[2], NULL, 16);
631 if (GpeNumber == ACPI_UINT32_MAX)
632 {
633 /* Conversion failed; invalid method, just ignore it */
634
632 DEBUG_PRINTP (ACPI_ERROR,
633 ("Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n",
635 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
636 "Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n",
637 Name));
638 return (AE_OK);
639 }
640
641 /* Ensure that we have a valid GPE number */
642
643 if (AcpiGbl_GpeValid[GpeNumber] == ACPI_GPE_INVALID)
644 {
645 /* Not valid, all we can do here is ignore it */
646
647 return (AE_OK);
648 }
649
650 /*
651 * Now we can add this information to the GpeInfo block
652 * for use during dispatch of this GPE.
653 */
654
655 AcpiGbl_GpeInfo [GpeNumber].Type = Type;
656 AcpiGbl_GpeInfo [GpeNumber].MethodHandle = ObjHandle;
657
658
659 /*
660 * Enable the GPE (SCIs should be disabled at this point)
661 */
662
663 AcpiHwEnableGpe (GpeNumber);
664
662 DEBUG_PRINTP (ACPI_INFO, ("Registered GPE method %s as GPE number %X\n",
665 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n",
666 Name, GpeNumber));
667 return (AE_OK);
668}
669
670
671/*******************************************************************************
672 *
673 * FUNCTION: AcpiEvInitGpeControlMethods
674 *
675 * PARAMETERS: None
676 *
677 * RETURN: None
678 *
679 * DESCRIPTION: Obtain the control methods associated with the GPEs.
680 *
681 * NOTE: Must be called AFTER namespace initialization!
682 *
683 ******************************************************************************/
684
685ACPI_STATUS
686AcpiEvInitGpeControlMethods (void)
687{
688 ACPI_STATUS Status;
689
690
691 FUNCTION_TRACE ("EvInitGpeControlMethods");
692
693
694 /* Get a permanent handle to the _GPE object */
695
696 Status = AcpiGetHandle (NULL, "\\_GPE", &AcpiGbl_GpeObjHandle);
697 if (ACPI_FAILURE (Status))
698 {
699 return_ACPI_STATUS (Status);
700 }
701
702 /* Traverse the namespace under \_GPE to find all methods there */
703
704 Status = AcpiWalkNamespace (ACPI_TYPE_METHOD, AcpiGbl_GpeObjHandle,
705 ACPI_UINT32_MAX, AcpiEvSaveMethodInfo,
706 NULL, NULL);
707
708 return_ACPI_STATUS (Status);
709}
710
711
712/*******************************************************************************
713 *
714 * FUNCTION: AcpiEvGpeDetect
715 *
716 * PARAMETERS: None
717 *
718 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
719 *
720 * DESCRIPTION: Detect if any GP events have occurred
721 *
722 ******************************************************************************/
723
724UINT32
725AcpiEvGpeDetect (void)
726{
727 UINT32 IntStatus = INTERRUPT_NOT_HANDLED;
728 UINT32 i;
729 UINT32 j;
730 UINT8 EnabledStatusByte;
731 UINT8 BitMask;
732
733
734 PROC_NAME ("EvGpeDetect");
735
736
737 /*
738 * Read all of the 8-bit GPE status and enable registers
739 * in both of the register blocks, saving all of it.
740 * Find all currently active GP events.
741 */
742 for (i = 0; i < AcpiGbl_GpeRegisterCount; i++)
743 {
744 AcpiOsReadPort (AcpiGbl_GpeRegisters[i].StatusAddr,
745 &AcpiGbl_GpeRegisters[i].Status, 8);
746
747 AcpiOsReadPort (AcpiGbl_GpeRegisters[i].EnableAddr,
748 &AcpiGbl_GpeRegisters[i].Enable, 8);
749
744 DEBUG_PRINT (TRACE_INTERRUPTS,
745 ("GPE block at %X - Enable %08X Status %08X\n",
750 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
751 "GPE block at %X - Enable %08X Status %08X\n",
752 AcpiGbl_GpeRegisters[i].EnableAddr,
753 AcpiGbl_GpeRegisters[i].Status,
754 AcpiGbl_GpeRegisters[i].Enable));
755
756 /* First check if there is anything active at all in this register */
757
758 EnabledStatusByte = (UINT8) (AcpiGbl_GpeRegisters[i].Status &
759 AcpiGbl_GpeRegisters[i].Enable);
760
761 if (!EnabledStatusByte)
762 {
763 /* No active GPEs in this register, move on */
764
765 continue;
766 }
767
768 /* Now look at the individual GPEs in this byte register */
769
770 for (j = 0, BitMask = 1; j < 8; j++, BitMask <<= 1)
771 {
772 /* Examine one GPE bit */
773
774 if (EnabledStatusByte & BitMask)
775 {
776 /*
777 * Found an active GPE. Dispatch the event to a handler
778 * or method.
779 */
780 IntStatus |= AcpiEvGpeDispatch (
781 AcpiGbl_GpeRegisters[i].GpeBase + j);
782 }
783 }
784 }
785
786 return (IntStatus);
787}
788
789
790/*******************************************************************************
791 *
792 * FUNCTION: AcpiEvAsynchExecuteGpeMethod
793 *
794 * PARAMETERS: GpeNumber - The 0-based Gpe number
795 *
796 * RETURN: None
797 *
798 * DESCRIPTION: Perform the actual execution of a GPE control method. This
799 * function is called from an invocation of AcpiOsQueueForExecution
800 * (and therefore does NOT execute at interrupt level) so that
801 * the control method itself is not executed in the context of
802 * the SCI interrupt handler.
803 *
804 ******************************************************************************/
805
806static void
807AcpiEvAsynchExecuteGpeMethod (
808 void *Context)
809{
810 UINT32 GpeNumber = (UINT32) Context;
811 ACPI_GPE_LEVEL_INFO GpeInfo;
812
813
814 FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
815
816 /*
817 * Take a snapshot of the GPE info for this level
818 */
819 AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
820 GpeInfo = AcpiGbl_GpeInfo [GpeNumber];
821 AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
822
823 /*
824 * Method Handler (_Lxx, _Exx):
825 * ----------------------------
826 * Evaluate the _Lxx/_Exx control method that corresponds to this GPE.
827 */
828 if (GpeInfo.MethodHandle)
829 {
830 AcpiNsEvaluateByHandle (GpeInfo.MethodHandle, NULL, NULL);
831 }
832
833 /*
834 * Level-Triggered?
835 * ----------------
836 * If level-triggered we clear the GPE status bit after handling the event.
837 */
838 if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
839 {
840 AcpiHwClearGpe (GpeNumber);
841 }
842
843 /*
844 * Enable the GPE.
845 */
846 AcpiHwEnableGpe (GpeNumber);
847
848 return_VOID;
849}
850
851
852/*******************************************************************************
853 *
854 * FUNCTION: AcpiEvGpeDispatch
855 *
856 * PARAMETERS: GpeNumber - The 0-based Gpe number
857 *
858 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
859 *
860 * DESCRIPTION: Handle and dispatch a General Purpose AcpiEvent.
861 * Clears the status bit for the requested event.
862 *
863 * TBD: [Investigate] is this still valid or necessary:
864 * The Gpe handler differs from the fixed events in that it clears the enable
865 * bit rather than the status bit to clear the interrupt. This allows
866 * software outside of interrupt context to determine what caused the SCI and
867 * dispatch the correct AML.
868 *
869 ******************************************************************************/
870
871UINT32
872AcpiEvGpeDispatch (
873 UINT32 GpeNumber)
874{
875 ACPI_GPE_LEVEL_INFO GpeInfo;
876
877 FUNCTION_TRACE ("EvGpeDispatch");
878
879
880 /*
881 * Valid GPE number?
882 */
883 if (AcpiGbl_GpeValid[GpeNumber] == ACPI_GPE_INVALID)
884 {
879 DEBUG_PRINTP (ACPI_ERROR, ("Invalid GPE bit [%X].\n", GpeNumber));
885 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid GPE bit [%X].\n", GpeNumber));
886 return_VALUE (INTERRUPT_NOT_HANDLED);
887 }
888
889 /*
890 * Disable the GPE.
891 */
892 AcpiHwDisableGpe (GpeNumber);
893
894 GpeInfo = AcpiGbl_GpeInfo [GpeNumber];
895
896 /*
897 * Edge-Triggered?
898 * ---------------
899 * If edge-triggered, clear the GPE status bit now. Note that
900 * level-triggered events are cleared after the GPE is serviced.
901 */
902 if (GpeInfo.Type & ACPI_EVENT_EDGE_TRIGGERED)
903 {
904 AcpiHwClearGpe (GpeNumber);
905 }
906 /*
907 * Function Handler (e.g. EC)?
908 */
909 if (GpeInfo.Handler)
910 {
911 /* Invoke function handler (at interrupt level). */
912
913 GpeInfo.Handler (GpeInfo.Context);
914
915 /* Level-Triggered? */
916
917 if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
918 {
919 AcpiHwClearGpe (GpeNumber);
920 }
921
922 /* Enable GPE */
923
924 AcpiHwEnableGpe (GpeNumber);
925 }
926
927 /*
928 * Method Handler (e.g. _Exx/_Lxx)?
929 */
930 else if (GpeInfo.MethodHandle)
931 {
932 if (ACPI_FAILURE(AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
933 AcpiEvAsynchExecuteGpeMethod, (void*) GpeNumber)))
934 {
935 /*
936 * Shoudn't occur, but if it does report an error. Note that
937 * the GPE will remain disabled until the ACPI Core Subsystem
938 * is restarted, or the handler is removed/reinstalled.
939 */
940 REPORT_ERROR (("AcpiEvGpeDispatch: Unable to queue handler for GPE bit [%X]\n", GpeNumber));
941 }
942 }
943
944 /*
945 * No Handler? Report an error and leave the GPE disabled.
946 */
947 else
948 {
949 REPORT_ERROR (("AcpiEvGpeDispatch: No installed handler for GPE [%X]\n", GpeNumber));
950
951 /* Level-Triggered? */
952
953 if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
954 {
955 AcpiHwClearGpe (GpeNumber);
956 }
957 }
958
959 return_VALUE (INTERRUPT_HANDLED);
960}