Ported ACPI CA (from the nice guys at Intel) to ReactOS (ACPI bus driver).
[reactos.git] / reactos / drivers / bus / acpi / events / evevent.c
1 /******************************************************************************
2 *
3 * Module Name: evevent - Fixed and General Purpose Acpi_event
4 * handling and dispatch
5 * $Revision: 1.1 $
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 }