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