:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / events / evevent.c
1 /******************************************************************************
2  *
3  * Module Name: evevent - Fixed and General Purpose Acpi_event
4  *                          handling and dispatch
5  *              $Revision$
6  *
7  *****************************************************************************/
8
9 /*
10  *  Copyright (C) 2000, 2001 R. Byron Moore
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27 #include "acpi.h"
28 #include "achware.h"
29 #include "acevents.h"
30 #include "acnamesp.h"
31 #include "accommon.h"
32
33 #define _COMPONENT          ACPI_EVENTS
34          MODULE_NAME         ("evevent")
35
36
37 /**************************************************************************
38  *
39  * FUNCTION:    Acpi_ev_initialize
40  *
41  * PARAMETERS:  None
42  *
43  * RETURN:      Status
44  *
45  * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly
46  *              configured, disables SCI event sources, installs the SCI
47  *              handler
48  *
49  *************************************************************************/
50
51 ACPI_STATUS
52 acpi_ev_initialize (
53         void)
54 {
55         ACPI_STATUS             status;
56
57
58         /* Make sure we have ACPI tables */
59
60         if (!acpi_gbl_DSDT) {
61                 return (AE_NO_ACPI_TABLES);
62         }
63
64
65         /* Make sure the BIOS supports ACPI mode */
66
67         if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) {
68                 return (AE_ERROR);
69         }
70
71
72         acpi_gbl_original_mode = acpi_hw_get_mode();
73
74         /*
75          * Initialize the Fixed and General Purpose Acpi_events prior. This is
76          * done prior to enabling SCIs to prevent interrupts from occuring
77          * before handers are installed.
78          */
79
80         status = acpi_ev_fixed_event_initialize ();
81         if (ACPI_FAILURE (status)) {
82                 return (status);
83         }
84
85         status = acpi_ev_gpe_initialize ();
86         if (ACPI_FAILURE (status)) {
87                 return (status);
88         }
89
90         /* Install the SCI handler */
91
92         status = acpi_ev_install_sci_handler ();
93         if (ACPI_FAILURE (status)) {
94                 return (status);
95         }
96
97
98         /* Install handlers for control method GPE handlers (_Lxx, _Exx) */
99
100         status = acpi_ev_init_gpe_control_methods ();
101         if (ACPI_FAILURE (status)) {
102                 return (status);
103         }
104
105         /* Install the handler for the Global Lock */
106
107         status = acpi_ev_init_global_lock_handler ();
108         if (ACPI_FAILURE (status)) {
109                 return (status);
110         }
111
112
113         return (status);
114 }
115
116
117 /******************************************************************************
118  *
119  * FUNCTION:    Acpi_ev_fixed_event_initialize
120  *
121  * PARAMETERS:  None
122  *
123  * RETURN:      Status
124  *
125  * DESCRIPTION: Initialize the Fixed Acpi_event data structures
126  *
127  ******************************************************************************/
128
129 ACPI_STATUS
130 acpi_ev_fixed_event_initialize(void)
131 {
132         int                     i = 0;
133
134         /* Initialize the structure that keeps track of fixed event handlers */
135
136         for (i = 0; i < NUM_FIXED_EVENTS; i++) {
137                 acpi_gbl_fixed_event_handlers[i].handler = NULL;
138                 acpi_gbl_fixed_event_handlers[i].context = NULL;
139         }
140
141         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0);
142         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0);
143         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0);
144         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0);
145         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0);
146
147         return (AE_OK);
148 }
149
150
151 /******************************************************************************
152  *
153  * FUNCTION:    Acpi_ev_fixed_event_detect
154  *
155  * PARAMETERS:  None
156  *
157  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
158  *
159  * DESCRIPTION: Checks the PM status register for fixed events
160  *
161  ******************************************************************************/
162
163 u32
164 acpi_ev_fixed_event_detect(void)
165 {
166         u32                     int_status = INTERRUPT_NOT_HANDLED;
167         u32                     status_register;
168         u32                     enable_register;
169
170         /*
171          * Read the fixed feature status and enable registers, as all the cases
172          * depend on their values.
173          */
174
175         status_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
176         enable_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
177
178
179         /* power management timer roll over */
180
181         if ((status_register & ACPI_STATUS_PMTIMER) &&
182                 (enable_register & ACPI_ENABLE_PMTIMER)) {
183                 int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER);
184         }
185
186         /* global event (BIOS want's the global lock) */
187
188         if ((status_register & ACPI_STATUS_GLOBAL) &&
189                 (enable_register & ACPI_ENABLE_GLOBAL)) {
190                 int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL);
191         }
192
193         /* power button event */
194
195         if ((status_register & ACPI_STATUS_POWER_BUTTON) &&
196                 (enable_register & ACPI_ENABLE_POWER_BUTTON)) {
197                 int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON);
198         }
199
200         /* sleep button event */
201
202         if ((status_register & ACPI_STATUS_SLEEP_BUTTON) &&
203                 (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) {
204                 int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON);
205         }
206
207         return (int_status);
208 }
209
210
211 /******************************************************************************
212  *
213  * FUNCTION:    Acpi_ev_fixed_event_dispatch
214  *
215  * PARAMETERS:  Event               - Event type
216  *
217  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
218  *
219  * DESCRIPTION: Clears the status bit for the requested event, calls the
220  *              handler that previously registered for the event.
221  *
222  ******************************************************************************/
223
224 u32
225 acpi_ev_fixed_event_dispatch (
226         u32                     event)
227 {
228         u32 register_id;
229
230         /* Clear the status bit */
231
232         switch (event) {
233         case ACPI_EVENT_PMTIMER:
234                 register_id = TMR_STS;
235                 break;
236
237         case ACPI_EVENT_GLOBAL:
238                 register_id = GBL_STS;
239                 break;
240
241         case ACPI_EVENT_POWER_BUTTON:
242                 register_id = PWRBTN_STS;
243                 break;
244
245         case ACPI_EVENT_SLEEP_BUTTON:
246                 register_id = SLPBTN_STS;
247                 break;
248
249         case ACPI_EVENT_RTC:
250                 register_id = RTC_STS;
251                 break;
252
253         default:
254                 return 0;
255                 break;
256         }
257
258         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 1);
259
260         /*
261          * Make sure we've got a handler.  If not, report an error.
262          * The event is disabled to prevent further interrupts.
263          */
264         if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
265                 register_id = (PM1_EN | REGISTER_BIT_ID(register_id));
266
267                 acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,
268                                  register_id, 0);
269
270                 REPORT_ERROR (
271                         ("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n",
272                         event));
273
274                 return (INTERRUPT_NOT_HANDLED);
275         }
276
277         /* Invoke the handler */
278
279         return ((acpi_gbl_fixed_event_handlers[event].handler)(
280                           acpi_gbl_fixed_event_handlers[event].context));
281 }
282
283
284 /******************************************************************************
285  *
286  * FUNCTION:    Acpi_ev_gpe_initialize
287  *
288  * PARAMETERS:  None
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: Initialize the GPE data structures
293  *
294  ******************************************************************************/
295
296 ACPI_STATUS
297 acpi_ev_gpe_initialize (void)
298 {
299         u32                     i;
300         u32                     j;
301         u32                     register_index;
302         u32                     gpe_number;
303         u16                     gpe0register_count;
304         u16                     gpe1_register_count;
305
306
307         /*
308          * Set up various GPE counts
309          *
310          * You may ask,why are the GPE register block lengths divided by 2?
311          * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event
312          * Registers, we have,
313          *
314          * "Each register block contains two registers of equal length
315          * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
316          * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
317          * The length of the GPE1_STS and GPE1_EN registers is equal to
318          * half the GPE1_LEN. If a generic register block is not supported
319          * then its respective block pointer and block length values in the
320          * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
321          * to be the same size."
322          */
323
324         gpe0register_count          = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
325         gpe1_register_count         = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
326         acpi_gbl_gpe_register_count = gpe0register_count + gpe1_register_count;
327
328         if (!acpi_gbl_gpe_register_count) {
329                 REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
330                 return (AE_OK);
331         }
332
333         /*
334          * Allocate the Gpe information block
335          */
336
337         acpi_gbl_gpe_registers = acpi_cm_callocate (acpi_gbl_gpe_register_count *
338                          sizeof (ACPI_GPE_REGISTERS));
339         if (!acpi_gbl_gpe_registers) {
340                 return (AE_NO_MEMORY);
341         }
342
343         /*
344          * Allocate the Gpe dispatch handler block
345          * There are eight distinct GP events per register.
346          * Initialization to zeros is sufficient
347          */
348
349         acpi_gbl_gpe_info = acpi_cm_callocate (MUL_8 (acpi_gbl_gpe_register_count) *
350                          sizeof (ACPI_GPE_LEVEL_INFO));
351         if (!acpi_gbl_gpe_info) {
352                 acpi_cm_free (acpi_gbl_gpe_registers);
353                 return (AE_NO_MEMORY);
354         }
355
356         /* Set the Gpe validation table to GPE_INVALID */
357
358         MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, NUM_GPE);
359
360         /*
361          * Initialize the Gpe information and validation blocks.  A goal of these
362          * blocks is to hide the fact that there are two separate GPE register sets
363          * In a given block, the status registers occupy the first half, and
364          * the enable registers occupy the second half.
365          */
366
367         /* GPE Block 0 */
368
369         register_index = 0;
370
371         for (i = 0; i < gpe0register_count; i++) {
372                 acpi_gbl_gpe_registers[register_index].status_addr =
373                                  (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i);
374
375                 acpi_gbl_gpe_registers[register_index].enable_addr =
376                                  (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i + gpe0register_count);
377
378                 acpi_gbl_gpe_registers[register_index].gpe_base = (u8) MUL_8 (i);
379
380                 for (j = 0; j < 8; j++) {
381                         gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j;
382                         acpi_gbl_gpe_valid[gpe_number] = (u8) register_index;
383                 }
384
385                 /*
386                  * Clear the status/enable registers.  Note that status registers
387                  * are cleared by writing a '1', while enable registers are cleared
388                  * by writing a '0'.
389                  */
390                 acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00);
391                 acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF);
392
393                 register_index++;
394         }
395
396         /* GPE Block 1 */
397
398         for (i = 0; i < gpe1_register_count; i++) {
399                 acpi_gbl_gpe_registers[register_index].status_addr =
400                                  (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i);
401
402                 acpi_gbl_gpe_registers[register_index].enable_addr =
403                                  (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i + gpe1_register_count);
404
405                 acpi_gbl_gpe_registers[register_index].gpe_base =
406                                  (u8) (acpi_gbl_FADT->gpe1_base + MUL_8 (i));
407
408                 for (j = 0; j < 8; j++) {
409                         gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j;
410                         acpi_gbl_gpe_valid[gpe_number] = (u8) register_index;
411                 }
412
413                 /*
414                  * Clear the status/enable registers.  Note that status registers
415                  * are cleared by writing a '1', while enable registers are cleared
416                  * by writing a '0'.
417                  */
418                 acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00);
419                 acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF);
420
421                 register_index++;
422         }
423
424         return (AE_OK);
425 }
426
427
428 /******************************************************************************
429  *
430  * FUNCTION:    Acpi_ev_save_method_info
431  *
432  * PARAMETERS:  None
433  *
434  * RETURN:      None
435  *
436  * DESCRIPTION: Called from Acpi_walk_namespace. Expects each object to be a
437  *              control method under the _GPE portion of the namespace.
438  *              Extract the name and GPE type from the object, saving this
439  *              information for quick lookup during GPE dispatch
440  *
441  *              The name of each GPE control method is of the form:
442  *                  "_Lnn" or "_Enn"
443  *              Where:
444  *                  L      - means that the GPE is level triggered
445  *                  E      - means that the GPE is edge triggered
446  *                  nn     - is the GPE number
447  *
448  ******************************************************************************/
449
450 static ACPI_STATUS
451 acpi_ev_save_method_info (
452         ACPI_HANDLE             obj_handle,
453         u32                     level,
454         void                    *obj_desc,
455         void                    **return_value)
456 {
457         u32                     gpe_number;
458         NATIVE_CHAR             name[ACPI_NAME_SIZE + 1];
459         u8                      type;
460
461
462         /* Extract the name from the object and convert to a string */
463
464         MOVE_UNALIGNED32_TO_32 (name, &((ACPI_NAMESPACE_NODE *) obj_handle)->name);
465         name[ACPI_NAME_SIZE] = 0;
466
467         /*
468          * Edge/Level determination is based on the 2nd s8 of the method name
469          */
470         if (name[1] == 'L') {
471                 type = ACPI_EVENT_LEVEL_TRIGGERED;
472         }
473         else if (name[1] == 'E') {
474                 type = ACPI_EVENT_EDGE_TRIGGERED;
475         }
476         else {
477                 /* Unknown method type, just ignore it! */
478
479                 return (AE_OK);
480         }
481
482         /* Convert the last two characters of the name to the Gpe Number */
483
484         gpe_number = STRTOUL (&name[2], NULL, 16);
485         if (gpe_number == ACPI_UINT32_MAX) {
486                 /* Conversion failed; invalid method, just ignore it */
487
488                 return (AE_OK);
489         }
490
491         /* Ensure that we have a valid GPE number */
492
493         if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
494                 /* Not valid, all we can do here is ignore it */
495
496                 return (AE_OK);
497         }
498
499         /*
500          * Now we can add this information to the Gpe_info block
501          * for use during dispatch of this GPE.
502          */
503
504         acpi_gbl_gpe_info [gpe_number].type         = type;
505         acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle;
506
507
508         /*
509          * Enable the GPE (SCIs should be disabled at this point)
510          */
511
512         acpi_hw_enable_gpe (gpe_number);
513
514         return (AE_OK);
515 }
516
517
518 /******************************************************************************
519  *
520  * FUNCTION:    Acpi_ev_init_gpe_control_methods
521  *
522  * PARAMETERS:  None
523  *
524  * RETURN:      None
525  *
526  * DESCRIPTION: Obtain the control methods associated with the GPEs.
527  *
528  *              NOTE: Must be called AFTER namespace initialization!
529  *
530  ******************************************************************************/
531
532 ACPI_STATUS
533 acpi_ev_init_gpe_control_methods (void)
534 {
535         ACPI_STATUS             status;
536
537
538         /* Get a permanent handle to the _GPE object */
539
540         status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle);
541         if (ACPI_FAILURE (status)) {
542                 return (status);
543         }
544
545         /* Traverse the namespace under \_GPE to find all methods there */
546
547         status = acpi_walk_namespace (ACPI_TYPE_METHOD, acpi_gbl_gpe_obj_handle,
548                           ACPI_UINT32_MAX, acpi_ev_save_method_info,
549                           NULL, NULL);
550
551         return (status);
552 }
553
554
555 /******************************************************************************
556  *
557  * FUNCTION:    Acpi_ev_gpe_detect
558  *
559  * PARAMETERS:  None
560  *
561  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
562  *
563  * DESCRIPTION: Detect if any GP events have occurred
564  *
565  ******************************************************************************/
566
567 u32
568 acpi_ev_gpe_detect (void)
569 {
570         u32                     int_status = INTERRUPT_NOT_HANDLED;
571         u32                     i;
572         u32                     j;
573         u8                      enabled_status_byte;
574         u8                      bit_mask;
575
576
577         /*
578          * Read all of the 8-bit GPE status and enable registers
579          * in both of the register blocks, saving all of it.
580          * Find all currently active GP events.
581          */
582
583         for (i = 0; i < acpi_gbl_gpe_register_count; i++) {
584                 acpi_gbl_gpe_registers[i].status =
585                                    acpi_os_in8 (acpi_gbl_gpe_registers[i].status_addr);
586
587                 acpi_gbl_gpe_registers[i].enable =
588                                    acpi_os_in8 (acpi_gbl_gpe_registers[i].enable_addr);
589
590                 /* First check if there is anything active at all in this register */
591
592                 enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status &
593                                   acpi_gbl_gpe_registers[i].enable);
594
595                 if (!enabled_status_byte) {
596                         /* No active GPEs in this register, move on */
597
598                         continue;
599                 }
600
601                 /* Now look at the individual GPEs in this byte register */
602
603                 for (j = 0, bit_mask = 1; j < 8; j++, bit_mask <<= 1) {
604                         /* Examine one GPE bit */
605
606                         if (enabled_status_byte & bit_mask) {
607                                 /*
608                                  * Found an active GPE.  Dispatch the event to a handler
609                                  * or method.
610                                  */
611                                 int_status |=
612                                         acpi_ev_gpe_dispatch (acpi_gbl_gpe_registers[i].gpe_base + j);
613                         }
614                 }
615         }
616
617         return (int_status);
618 }
619
620
621 /******************************************************************************
622  *
623  * FUNCTION:    Acpi_ev_asynch_execute_gpe_method
624  *
625  * PARAMETERS:  Gpe_number      - The 0-based Gpe number
626  *
627  * RETURN:      None
628  *
629  * DESCRIPTION: Perform the actual execution of a GPE control method.  This
630  *              function is called from an invocation of Acpi_os_queue_for_execution
631  *              (and therefore does NOT execute at interrupt level) so that
632  *              the control method itself is not executed in the context of
633  *              the SCI interrupt handler.
634  *
635  ******************************************************************************/
636
637 static void
638 acpi_ev_asynch_execute_gpe_method (
639         void                    *context)
640 {
641         u32                     gpe_number = (u32) context;
642         ACPI_GPE_LEVEL_INFO     gpe_info;
643
644
645         /*
646          * Take a snapshot of the GPE info for this level
647          */
648         acpi_cm_acquire_mutex (ACPI_MTX_EVENTS);
649         gpe_info = acpi_gbl_gpe_info [gpe_number];
650         acpi_cm_release_mutex (ACPI_MTX_EVENTS);
651
652         /*
653          * Method Handler (_Lxx, _Exx):
654          * ----------------------------
655          * Evaluate the _Lxx/_Exx control method that corresponds to this GPE.
656          */
657         if (gpe_info.method_handle) {
658                 acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL);
659         }
660
661         /*
662          * Level-Triggered?
663          * ----------------
664          * If level-triggered we clear the GPE status bit after handling the event.
665          */
666         if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
667                 acpi_hw_clear_gpe (gpe_number);
668         }
669
670         /*
671          * Enable the GPE.
672          */
673         acpi_hw_enable_gpe (gpe_number);
674
675         return;
676 }
677
678
679 /******************************************************************************
680  *
681  * FUNCTION:    Acpi_ev_gpe_dispatch
682  *
683  * PARAMETERS:  Gpe_number      - The 0-based Gpe number
684  *
685  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
686  *
687  * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event.
688  *              Clears the status bit for the requested event.
689  *
690  * TBD: [Investigate] is this still valid or necessary:
691  * The Gpe handler differs from the fixed events in that it clears the enable
692  * bit rather than the status bit to clear the interrupt.  This allows
693  * software outside of interrupt context to determine what caused the SCI and
694  * dispatch the correct AML.
695  *
696  ******************************************************************************/
697
698 u32
699 acpi_ev_gpe_dispatch (
700         u32                     gpe_number)
701 {
702         ACPI_GPE_LEVEL_INFO     gpe_info;
703
704         /*
705          * Valid GPE number?
706          */
707         if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
708                 return (INTERRUPT_NOT_HANDLED);
709         }
710
711         /*
712          * Disable the GPE.
713          */
714         acpi_hw_disable_gpe (gpe_number);
715
716         gpe_info = acpi_gbl_gpe_info [gpe_number];
717
718         /*
719          * Edge-Triggered?
720          * ---------------
721          * If edge-triggered, clear the GPE status bit now.  Note that
722          * level-triggered events are cleared after the GPE is serviced.
723          */
724         if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) {
725                 acpi_hw_clear_gpe (gpe_number);
726         }
727                 /*
728                  * Function Handler (e.g. EC)?
729                  */
730         if (gpe_info.handler) {
731                 /* Invoke function handler (at interrupt level). */
732                 gpe_info.handler (gpe_info.context);
733
734                 /* Level-Triggered? */
735                 if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
736                         acpi_hw_clear_gpe (gpe_number);
737                 }
738
739                 /* Enable GPE */
740                 acpi_hw_enable_gpe (gpe_number);
741         }
742         /*
743          * Method Handler (e.g. _Exx/_Lxx)?
744          */
745         else if (gpe_info.method_handle) {
746                 if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
747                         acpi_ev_asynch_execute_gpe_method, (void*)(NATIVE_UINT)gpe_number))) {
748                         /*
749                          * Shoudn't occur, but if it does report an error. Note that
750                          * the GPE will remain disabled until the ACPI Core Subsystem
751                          * is restarted, or the handler is removed/reinstalled.
752                          */
753                         REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number));
754                 }
755         }
756         /*
757          * No Handler? Report an error and leave the GPE disabled.
758          */
759         else {
760                 REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number));
761
762                 /* Level-Triggered? */
763                 if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
764                         acpi_hw_clear_gpe (gpe_number);
765                 }
766         }
767
768         return (INTERRUPT_HANDLED);
769 }