1 /******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #define EXPORT_ACPI_INTERFACES
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acnamesp.h"
49 #include "acevents.h"
50 #include "acinterp.h"
51
52 #define _COMPONENT ACPI_EVENTS
53 ACPI_MODULE_NAME ("evxface")
54
55 #if (!ACPI_REDUCED_HARDWARE)
56
57 /* Local prototypes */
58
59 static ACPI_STATUS
60 AcpiEvInstallGpeHandler (
61 ACPI_HANDLE GpeDevice,
62 UINT32 GpeNumber,
63 UINT32 Type,
64 BOOLEAN IsRawHandler,
65 ACPI_GPE_HANDLER Address,
66 void *Context);
67
68 #endif
69
70
71 /*******************************************************************************
72 *
73 * FUNCTION: AcpiInstallNotifyHandler
74 *
75 * PARAMETERS: Device - The device for which notifies will be handled
76 * HandlerType - The type of handler:
77 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
78 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
79 * ACPI_ALL_NOTIFY: Both System and Device
80 * Handler - Address of the handler
81 * Context - Value passed to the handler on each GPE
82 *
83 * RETURN: Status
84 *
85 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
86 * ThermalZone, or Processor object.
87 *
88 * NOTES: The Root namespace object may have only one handler for each
89 * type of notify (System/Device). Device/Thermal/Processor objects
90 * may have one device notify handler, and multiple system notify
91 * handlers.
92 *
93 ******************************************************************************/
94
95 ACPI_STATUS
AcpiInstallNotifyHandler(ACPI_HANDLE Device,UINT32 HandlerType,ACPI_NOTIFY_HANDLER Handler,void * Context)96 AcpiInstallNotifyHandler (
97 ACPI_HANDLE Device,
98 UINT32 HandlerType,
99 ACPI_NOTIFY_HANDLER Handler,
100 void *Context)
101 {
102 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
103 ACPI_OPERAND_OBJECT *ObjDesc;
104 ACPI_OPERAND_OBJECT *HandlerObj;
105 ACPI_STATUS Status;
106 UINT32 i;
107
108
109 ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
110
111
112 /* Parameter validation */
113
114 if ((!Device) || (!Handler) || (!HandlerType) ||
115 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
116 {
117 return_ACPI_STATUS (AE_BAD_PARAMETER);
118 }
119
120 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
121 if (ACPI_FAILURE (Status))
122 {
123 return_ACPI_STATUS (Status);
124 }
125
126 /*
127 * Root Object:
128 * Registering a notify handler on the root object indicates that the
129 * caller wishes to receive notifications for all objects. Note that
130 * only one global handler can be registered per notify type.
131 * Ensure that a handler is not already installed.
132 */
133 if (Device == ACPI_ROOT_OBJECT)
134 {
135 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
136 {
137 if (HandlerType & (i+1))
138 {
139 if (AcpiGbl_GlobalNotify[i].Handler)
140 {
141 Status = AE_ALREADY_EXISTS;
142 goto UnlockAndExit;
143 }
144
145 AcpiGbl_GlobalNotify[i].Handler = Handler;
146 AcpiGbl_GlobalNotify[i].Context = Context;
147 }
148 }
149
150 goto UnlockAndExit; /* Global notify handler installed, all done */
151 }
152
153 /*
154 * All Other Objects:
155 * Caller will only receive notifications specific to the target
156 * object. Note that only certain object types are allowed to
157 * receive notifications.
158 */
159
160 /* Are Notifies allowed on this object? */
161
162 if (!AcpiEvIsNotifyObject (Node))
163 {
164 Status = AE_TYPE;
165 goto UnlockAndExit;
166 }
167
168 /* Check for an existing internal object, might not exist */
169
170 ObjDesc = AcpiNsGetAttachedObject (Node);
171 if (!ObjDesc)
172 {
173 /* Create a new object */
174
175 ObjDesc = AcpiUtCreateInternalObject (Node->Type);
176 if (!ObjDesc)
177 {
178 Status = AE_NO_MEMORY;
179 goto UnlockAndExit;
180 }
181
182 /* Attach new object to the Node, remove local reference */
183
184 Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
185 AcpiUtRemoveReference (ObjDesc);
186 if (ACPI_FAILURE (Status))
187 {
188 goto UnlockAndExit;
189 }
190 }
191
192 /* Ensure that the handler is not already installed in the lists */
193
194 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
195 {
196 if (HandlerType & (i+1))
197 {
198 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
199 while (HandlerObj)
200 {
201 if (HandlerObj->Notify.Handler == Handler)
202 {
203 Status = AE_ALREADY_EXISTS;
204 goto UnlockAndExit;
205 }
206
207 HandlerObj = HandlerObj->Notify.Next[i];
208 }
209 }
210 }
211
212 /* Create and populate a new notify handler object */
213
214 HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
215 if (!HandlerObj)
216 {
217 Status = AE_NO_MEMORY;
218 goto UnlockAndExit;
219 }
220
221 HandlerObj->Notify.Node = Node;
222 HandlerObj->Notify.HandlerType = HandlerType;
223 HandlerObj->Notify.Handler = Handler;
224 HandlerObj->Notify.Context = Context;
225
226 /* Install the handler at the list head(s) */
227
228 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
229 {
230 if (HandlerType & (i+1))
231 {
232 HandlerObj->Notify.Next[i] =
233 ObjDesc->CommonNotify.NotifyList[i];
234
235 ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
236 }
237 }
238
239 /* Add an extra reference if handler was installed in both lists */
240
241 if (HandlerType == ACPI_ALL_NOTIFY)
242 {
243 AcpiUtAddReference (HandlerObj);
244 }
245
246
247 UnlockAndExit:
248 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
249 return_ACPI_STATUS (Status);
250 }
251
ACPI_EXPORT_SYMBOL(AcpiInstallNotifyHandler)252 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
253
254
255 /*******************************************************************************
256 *
257 * FUNCTION: AcpiRemoveNotifyHandler
258 *
259 * PARAMETERS: Device - The device for which the handler is installed
260 * HandlerType - The type of handler:
261 * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
262 * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
263 * ACPI_ALL_NOTIFY: Both System and Device
264 * Handler - Address of the handler
265 *
266 * RETURN: Status
267 *
268 * DESCRIPTION: Remove a handler for notifies on an ACPI device
269 *
270 ******************************************************************************/
271
272 ACPI_STATUS
273 AcpiRemoveNotifyHandler (
274 ACPI_HANDLE Device,
275 UINT32 HandlerType,
276 ACPI_NOTIFY_HANDLER Handler)
277 {
278 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
279 ACPI_OPERAND_OBJECT *ObjDesc;
280 ACPI_OPERAND_OBJECT *HandlerObj;
281 ACPI_OPERAND_OBJECT *PreviousHandlerObj;
282 ACPI_STATUS Status = AE_OK;
283 UINT32 i;
284
285
286 ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
287
288
289 /* Parameter validation */
290
291 if ((!Device) || (!Handler) || (!HandlerType) ||
292 (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
293 {
294 return_ACPI_STATUS (AE_BAD_PARAMETER);
295 }
296
297 /* Root Object. Global handlers are removed here */
298
299 if (Device == ACPI_ROOT_OBJECT)
300 {
301 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
302 {
303 if (HandlerType & (i+1))
304 {
305 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
306 if (ACPI_FAILURE (Status))
307 {
308 return_ACPI_STATUS (Status);
309 }
310
311 if (!AcpiGbl_GlobalNotify[i].Handler ||
312 (AcpiGbl_GlobalNotify[i].Handler != Handler))
313 {
314 Status = AE_NOT_EXIST;
315 goto UnlockAndExit;
316 }
317
318 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
319 "Removing global notify handler\n"));
320
321 AcpiGbl_GlobalNotify[i].Handler = NULL;
322 AcpiGbl_GlobalNotify[i].Context = NULL;
323
324 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
325
326 /* Make sure all deferred notify tasks are completed */
327
328 AcpiOsWaitEventsComplete ();
329 }
330 }
331
332 return_ACPI_STATUS (AE_OK);
333 }
334
335 /* All other objects: Are Notifies allowed on this object? */
336
337 if (!AcpiEvIsNotifyObject (Node))
338 {
339 return_ACPI_STATUS (AE_TYPE);
340 }
341
342 /* Must have an existing internal object */
343
344 ObjDesc = AcpiNsGetAttachedObject (Node);
345 if (!ObjDesc)
346 {
347 return_ACPI_STATUS (AE_NOT_EXIST);
348 }
349
350 /* Internal object exists. Find the handler and remove it */
351
352 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
353 {
354 if (HandlerType & (i+1))
355 {
356 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
357 if (ACPI_FAILURE (Status))
358 {
359 return_ACPI_STATUS (Status);
360 }
361
362 HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
363 PreviousHandlerObj = NULL;
364
365 /* Attempt to find the handler in the handler list */
366
367 while (HandlerObj &&
368 (HandlerObj->Notify.Handler != Handler))
369 {
370 PreviousHandlerObj = HandlerObj;
371 HandlerObj = HandlerObj->Notify.Next[i];
372 }
373
374 if (!HandlerObj)
375 {
376 Status = AE_NOT_EXIST;
377 goto UnlockAndExit;
378 }
379
380 /* Remove the handler object from the list */
381
382 if (PreviousHandlerObj) /* Handler is not at the list head */
383 {
384 PreviousHandlerObj->Notify.Next[i] =
385 HandlerObj->Notify.Next[i];
386 }
387 else /* Handler is at the list head */
388 {
389 ObjDesc->CommonNotify.NotifyList[i] =
390 HandlerObj->Notify.Next[i];
391 }
392
393 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
394
395 /* Make sure all deferred notify tasks are completed */
396
397 AcpiOsWaitEventsComplete ();
398 AcpiUtRemoveReference (HandlerObj);
399 }
400 }
401
402 return_ACPI_STATUS (Status);
403
404
405 UnlockAndExit:
406 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
407 return_ACPI_STATUS (Status);
408 }
409
ACPI_EXPORT_SYMBOL(AcpiRemoveNotifyHandler)410 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
411
412
413 /*******************************************************************************
414 *
415 * FUNCTION: AcpiInstallExceptionHandler
416 *
417 * PARAMETERS: Handler - Pointer to the handler function for the
418 * event
419 *
420 * RETURN: Status
421 *
422 * DESCRIPTION: Saves the pointer to the handler function
423 *
424 ******************************************************************************/
425
426 ACPI_STATUS
427 AcpiInstallExceptionHandler (
428 ACPI_EXCEPTION_HANDLER Handler)
429 {
430 ACPI_STATUS Status;
431
432
433 ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
434
435
436 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
437 if (ACPI_FAILURE (Status))
438 {
439 return_ACPI_STATUS (Status);
440 }
441
442 /* Don't allow two handlers. */
443
444 if (AcpiGbl_ExceptionHandler)
445 {
446 Status = AE_ALREADY_EXISTS;
447 goto Cleanup;
448 }
449
450 /* Install the handler */
451
452 AcpiGbl_ExceptionHandler = Handler;
453
454 Cleanup:
455 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
456 return_ACPI_STATUS (Status);
457 }
458
ACPI_EXPORT_SYMBOL(AcpiInstallExceptionHandler)459 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
460
461
462 #if (!ACPI_REDUCED_HARDWARE)
463 /*******************************************************************************
464 *
465 * FUNCTION: AcpiInstallSciHandler
466 *
467 * PARAMETERS: Address - Address of the handler
468 * Context - Value passed to the handler on each SCI
469 *
470 * RETURN: Status
471 *
472 * DESCRIPTION: Install a handler for a System Control Interrupt.
473 *
474 ******************************************************************************/
475
476 ACPI_STATUS
477 AcpiInstallSciHandler (
478 ACPI_SCI_HANDLER Address,
479 void *Context)
480 {
481 ACPI_SCI_HANDLER_INFO *NewSciHandler;
482 ACPI_SCI_HANDLER_INFO *SciHandler;
483 ACPI_CPU_FLAGS Flags;
484 ACPI_STATUS Status;
485
486
487 ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
488
489
490 if (!Address)
491 {
492 return_ACPI_STATUS (AE_BAD_PARAMETER);
493 }
494
495 /* Allocate and init a handler object */
496
497 NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
498 if (!NewSciHandler)
499 {
500 return_ACPI_STATUS (AE_NO_MEMORY);
501 }
502
503 NewSciHandler->Address = Address;
504 NewSciHandler->Context = Context;
505
506 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
507 if (ACPI_FAILURE (Status))
508 {
509 goto Exit;
510 }
511
512 /* Lock list during installation */
513
514 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
515 SciHandler = AcpiGbl_SciHandlerList;
516
517 /* Ensure handler does not already exist */
518
519 while (SciHandler)
520 {
521 if (Address == SciHandler->Address)
522 {
523 Status = AE_ALREADY_EXISTS;
524 goto UnlockAndExit;
525 }
526
527 SciHandler = SciHandler->Next;
528 }
529
530 /* Install the new handler into the global list (at head) */
531
532 NewSciHandler->Next = AcpiGbl_SciHandlerList;
533 AcpiGbl_SciHandlerList = NewSciHandler;
534
535
536 UnlockAndExit:
537
538 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
539 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
540
541 Exit:
542 if (ACPI_FAILURE (Status))
543 {
544 ACPI_FREE (NewSciHandler);
545 }
546 return_ACPI_STATUS (Status);
547 }
548
ACPI_EXPORT_SYMBOL(AcpiInstallSciHandler)549 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
550
551
552 /*******************************************************************************
553 *
554 * FUNCTION: AcpiRemoveSciHandler
555 *
556 * PARAMETERS: Address - Address of the handler
557 *
558 * RETURN: Status
559 *
560 * DESCRIPTION: Remove a handler for a System Control Interrupt.
561 *
562 ******************************************************************************/
563
564 ACPI_STATUS
565 AcpiRemoveSciHandler (
566 ACPI_SCI_HANDLER Address)
567 {
568 ACPI_SCI_HANDLER_INFO *PrevSciHandler;
569 ACPI_SCI_HANDLER_INFO *NextSciHandler;
570 ACPI_CPU_FLAGS Flags;
571 ACPI_STATUS Status;
572
573
574 ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
575
576
577 if (!Address)
578 {
579 return_ACPI_STATUS (AE_BAD_PARAMETER);
580 }
581
582 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
583 if (ACPI_FAILURE (Status))
584 {
585 return_ACPI_STATUS (Status);
586 }
587
588 /* Remove the SCI handler with lock */
589
590 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
591
592 PrevSciHandler = NULL;
593 NextSciHandler = AcpiGbl_SciHandlerList;
594 while (NextSciHandler)
595 {
596 if (NextSciHandler->Address == Address)
597 {
598 /* Unlink and free the SCI handler info block */
599
600 if (PrevSciHandler)
601 {
602 PrevSciHandler->Next = NextSciHandler->Next;
603 }
604 else
605 {
606 AcpiGbl_SciHandlerList = NextSciHandler->Next;
607 }
608
609 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
610 ACPI_FREE (NextSciHandler);
611 goto UnlockAndExit;
612 }
613
614 PrevSciHandler = NextSciHandler;
615 NextSciHandler = NextSciHandler->Next;
616 }
617
618 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
619 Status = AE_NOT_EXIST;
620
621
622 UnlockAndExit:
623 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
624 return_ACPI_STATUS (Status);
625 }
626
ACPI_EXPORT_SYMBOL(AcpiRemoveSciHandler)627 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
628
629
630 /*******************************************************************************
631 *
632 * FUNCTION: AcpiInstallGlobalEventHandler
633 *
634 * PARAMETERS: Handler - Pointer to the global event handler function
635 * Context - Value passed to the handler on each event
636 *
637 * RETURN: Status
638 *
639 * DESCRIPTION: Saves the pointer to the handler function. The global handler
640 * is invoked upon each incoming GPE and Fixed Event. It is
641 * invoked at interrupt level at the time of the event dispatch.
642 * Can be used to update event counters, etc.
643 *
644 ******************************************************************************/
645
646 ACPI_STATUS
647 AcpiInstallGlobalEventHandler (
648 ACPI_GBL_EVENT_HANDLER Handler,
649 void *Context)
650 {
651 ACPI_STATUS Status;
652
653
654 ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
655
656
657 /* Parameter validation */
658
659 if (!Handler)
660 {
661 return_ACPI_STATUS (AE_BAD_PARAMETER);
662 }
663
664 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
665 if (ACPI_FAILURE (Status))
666 {
667 return_ACPI_STATUS (Status);
668 }
669
670 /* Don't allow two handlers. */
671
672 if (AcpiGbl_GlobalEventHandler)
673 {
674 Status = AE_ALREADY_EXISTS;
675 goto Cleanup;
676 }
677
678 AcpiGbl_GlobalEventHandler = Handler;
679 AcpiGbl_GlobalEventHandlerContext = Context;
680
681
682 Cleanup:
683 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
684 return_ACPI_STATUS (Status);
685 }
686
ACPI_EXPORT_SYMBOL(AcpiInstallGlobalEventHandler)687 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
688
689
690 /*******************************************************************************
691 *
692 * FUNCTION: AcpiInstallFixedEventHandler
693 *
694 * PARAMETERS: Event - Event type to enable.
695 * Handler - Pointer to the handler function for the
696 * event
697 * Context - Value passed to the handler on each GPE
698 *
699 * RETURN: Status
700 *
701 * DESCRIPTION: Saves the pointer to the handler function and then enables the
702 * event.
703 *
704 ******************************************************************************/
705
706 ACPI_STATUS
707 AcpiInstallFixedEventHandler (
708 UINT32 Event,
709 ACPI_EVENT_HANDLER Handler,
710 void *Context)
711 {
712 ACPI_STATUS Status;
713
714
715 ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
716
717
718 /* Parameter validation */
719
720 if (Event > ACPI_EVENT_MAX)
721 {
722 return_ACPI_STATUS (AE_BAD_PARAMETER);
723 }
724
725 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
726 if (ACPI_FAILURE (Status))
727 {
728 return_ACPI_STATUS (Status);
729 }
730
731 /* Do not allow multiple handlers */
732
733 if (AcpiGbl_FixedEventHandlers[Event].Handler)
734 {
735 Status = AE_ALREADY_EXISTS;
736 goto Cleanup;
737 }
738
739 /* Install the handler before enabling the event */
740
741 AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
742 AcpiGbl_FixedEventHandlers[Event].Context = Context;
743
744 Status = AcpiEnableEvent (Event, 0);
745 if (ACPI_FAILURE (Status))
746 {
747 ACPI_WARNING ((AE_INFO,
748 "Could not enable fixed event - %s (%u)",
749 AcpiUtGetEventName (Event), Event));
750
751 /* Remove the handler */
752
753 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
754 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
755 }
756 else
757 {
758 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
759 "Enabled fixed event %s (%X), Handler=%p\n",
760 AcpiUtGetEventName (Event), Event, Handler));
761 }
762
763
764 Cleanup:
765 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
766 return_ACPI_STATUS (Status);
767 }
768
ACPI_EXPORT_SYMBOL(AcpiInstallFixedEventHandler)769 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
770
771
772 /*******************************************************************************
773 *
774 * FUNCTION: AcpiRemoveFixedEventHandler
775 *
776 * PARAMETERS: Event - Event type to disable.
777 * Handler - Address of the handler
778 *
779 * RETURN: Status
780 *
781 * DESCRIPTION: Disables the event and unregisters the event handler.
782 *
783 ******************************************************************************/
784
785 ACPI_STATUS
786 AcpiRemoveFixedEventHandler (
787 UINT32 Event,
788 ACPI_EVENT_HANDLER Handler)
789 {
790 ACPI_STATUS Status = AE_OK;
791
792
793 ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
794
795
796 /* Parameter validation */
797
798 if (Event > ACPI_EVENT_MAX)
799 {
800 return_ACPI_STATUS (AE_BAD_PARAMETER);
801 }
802
803 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
804 if (ACPI_FAILURE (Status))
805 {
806 return_ACPI_STATUS (Status);
807 }
808
809 /* Disable the event before removing the handler */
810
811 Status = AcpiDisableEvent (Event, 0);
812
813 /* Always Remove the handler */
814
815 AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
816 AcpiGbl_FixedEventHandlers[Event].Context = NULL;
817
818 if (ACPI_FAILURE (Status))
819 {
820 ACPI_WARNING ((AE_INFO,
821 "Could not disable fixed event - %s (%u)",
822 AcpiUtGetEventName (Event), Event));
823 }
824 else
825 {
826 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
827 "Disabled fixed event - %s (%X)\n",
828 AcpiUtGetEventName (Event), Event));
829 }
830
831 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
832 return_ACPI_STATUS (Status);
833 }
834
ACPI_EXPORT_SYMBOL(AcpiRemoveFixedEventHandler)835 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
836
837
838 /*******************************************************************************
839 *
840 * FUNCTION: AcpiEvInstallGpeHandler
841 *
842 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
843 * defined GPEs)
844 * GpeNumber - The GPE number within the GPE block
845 * Type - Whether this GPE should be treated as an
846 * edge- or level-triggered interrupt.
847 * IsRawHandler - Whether this GPE should be handled using
848 * the special GPE handler mode.
849 * Address - Address of the handler
850 * Context - Value passed to the handler on each GPE
851 *
852 * RETURN: Status
853 *
854 * DESCRIPTION: Internal function to install a handler for a General Purpose
855 * Event.
856 *
857 ******************************************************************************/
858
859 static ACPI_STATUS
860 AcpiEvInstallGpeHandler (
861 ACPI_HANDLE GpeDevice,
862 UINT32 GpeNumber,
863 UINT32 Type,
864 BOOLEAN IsRawHandler,
865 ACPI_GPE_HANDLER Address,
866 void *Context)
867 {
868 ACPI_GPE_EVENT_INFO *GpeEventInfo;
869 ACPI_GPE_HANDLER_INFO *Handler;
870 ACPI_STATUS Status;
871 ACPI_CPU_FLAGS Flags;
872
873
874 ACPI_FUNCTION_TRACE (EvInstallGpeHandler);
875
876
877 /* Parameter validation */
878
879 if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
880 {
881 return_ACPI_STATUS (AE_BAD_PARAMETER);
882 }
883
884 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
885 if (ACPI_FAILURE (Status))
886 {
887 return_ACPI_STATUS (Status);
888 }
889
890 /* Allocate and init handler object (before lock) */
891
892 Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
893 if (!Handler)
894 {
895 Status = AE_NO_MEMORY;
896 goto UnlockAndExit;
897 }
898
899 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
900
901 /* Ensure that we have a valid GPE number */
902
903 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
904 if (!GpeEventInfo)
905 {
906 Status = AE_BAD_PARAMETER;
907 goto FreeAndExit;
908 }
909
910 /* Make sure that there isn't a handler there already */
911
912 if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
913 ACPI_GPE_DISPATCH_HANDLER) ||
914 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
915 ACPI_GPE_DISPATCH_RAW_HANDLER))
916 {
917 Status = AE_ALREADY_EXISTS;
918 goto FreeAndExit;
919 }
920
921 Handler->Address = Address;
922 Handler->Context = Context;
923 Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
924 Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
925 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
926
927 /*
928 * If the GPE is associated with a method, it may have been enabled
929 * automatically during initialization, in which case it has to be
930 * disabled now to avoid spurious execution of the handler.
931 */
932 if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
933 ACPI_GPE_DISPATCH_METHOD) ||
934 (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
935 ACPI_GPE_DISPATCH_NOTIFY)) &&
936 GpeEventInfo->RuntimeCount)
937 {
938 Handler->OriginallyEnabled = TRUE;
939 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
940
941 /* Sanity check of original type against new type */
942
943 if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
944 {
945 ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
946 }
947 }
948
949 /* Install the handler */
950
951 GpeEventInfo->Dispatch.Handler = Handler;
952
953 /* Setup up dispatch flags to indicate handler (vs. method/notify) */
954
955 GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
956 GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ?
957 ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER));
958
959 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
960
961
962 UnlockAndExit:
963 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
964 return_ACPI_STATUS (Status);
965
966 FreeAndExit:
967 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
968 ACPI_FREE (Handler);
969 goto UnlockAndExit;
970 }
971
972
973 /*******************************************************************************
974 *
975 * FUNCTION: AcpiInstallGpeHandler
976 *
977 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
978 * defined GPEs)
979 * GpeNumber - The GPE number within the GPE block
980 * Type - Whether this GPE should be treated as an
981 * edge- or level-triggered interrupt.
982 * Address - Address of the handler
983 * Context - Value passed to the handler on each GPE
984 *
985 * RETURN: Status
986 *
987 * DESCRIPTION: Install a handler for a General Purpose Event.
988 *
989 ******************************************************************************/
990
991 ACPI_STATUS
AcpiInstallGpeHandler(ACPI_HANDLE GpeDevice,UINT32 GpeNumber,UINT32 Type,ACPI_GPE_HANDLER Address,void * Context)992 AcpiInstallGpeHandler (
993 ACPI_HANDLE GpeDevice,
994 UINT32 GpeNumber,
995 UINT32 Type,
996 ACPI_GPE_HANDLER Address,
997 void *Context)
998 {
999 ACPI_STATUS Status;
1000
1001
1002 ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
1003
1004
1005 Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1006 FALSE, Address, Context);
1007
1008 return_ACPI_STATUS (Status);
1009 }
1010
ACPI_EXPORT_SYMBOL(AcpiInstallGpeHandler)1011 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
1012
1013
1014 /*******************************************************************************
1015 *
1016 * FUNCTION: AcpiInstallGpeRawHandler
1017 *
1018 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
1019 * defined GPEs)
1020 * GpeNumber - The GPE number within the GPE block
1021 * Type - Whether this GPE should be treated as an
1022 * edge- or level-triggered interrupt.
1023 * Address - Address of the handler
1024 * Context - Value passed to the handler on each GPE
1025 *
1026 * RETURN: Status
1027 *
1028 * DESCRIPTION: Install a handler for a General Purpose Event.
1029 *
1030 ******************************************************************************/
1031
1032 ACPI_STATUS
1033 AcpiInstallGpeRawHandler (
1034 ACPI_HANDLE GpeDevice,
1035 UINT32 GpeNumber,
1036 UINT32 Type,
1037 ACPI_GPE_HANDLER Address,
1038 void *Context)
1039 {
1040 ACPI_STATUS Status;
1041
1042
1043 ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler);
1044
1045
1046 Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1047 TRUE, Address, Context);
1048
1049 return_ACPI_STATUS (Status);
1050 }
1051
ACPI_EXPORT_SYMBOL(AcpiInstallGpeRawHandler)1052 ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler)
1053
1054
1055 /*******************************************************************************
1056 *
1057 * FUNCTION: AcpiRemoveGpeHandler
1058 *
1059 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT
1060 * defined GPEs)
1061 * GpeNumber - The event to remove a handler
1062 * Address - Address of the handler
1063 *
1064 * RETURN: Status
1065 *
1066 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
1067 *
1068 ******************************************************************************/
1069
1070 ACPI_STATUS
1071 AcpiRemoveGpeHandler (
1072 ACPI_HANDLE GpeDevice,
1073 UINT32 GpeNumber,
1074 ACPI_GPE_HANDLER Address)
1075 {
1076 ACPI_GPE_EVENT_INFO *GpeEventInfo;
1077 ACPI_GPE_HANDLER_INFO *Handler;
1078 ACPI_STATUS Status;
1079 ACPI_CPU_FLAGS Flags;
1080
1081
1082 ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
1083
1084
1085 /* Parameter validation */
1086
1087 if (!Address)
1088 {
1089 return_ACPI_STATUS (AE_BAD_PARAMETER);
1090 }
1091
1092 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1093 if (ACPI_FAILURE (Status))
1094 {
1095 return_ACPI_STATUS (Status);
1096 }
1097
1098 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1099
1100 /* Ensure that we have a valid GPE number */
1101
1102 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1103 if (!GpeEventInfo)
1104 {
1105 Status = AE_BAD_PARAMETER;
1106 goto UnlockAndExit;
1107 }
1108
1109 /* Make sure that a handler is indeed installed */
1110
1111 if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1112 ACPI_GPE_DISPATCH_HANDLER) &&
1113 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1114 ACPI_GPE_DISPATCH_RAW_HANDLER))
1115 {
1116 Status = AE_NOT_EXIST;
1117 goto UnlockAndExit;
1118 }
1119
1120 /* Make sure that the installed handler is the same */
1121
1122 if (GpeEventInfo->Dispatch.Handler->Address != Address)
1123 {
1124 Status = AE_BAD_PARAMETER;
1125 goto UnlockAndExit;
1126 }
1127
1128 /* Remove the handler */
1129
1130 Handler = GpeEventInfo->Dispatch.Handler;
1131 GpeEventInfo->Dispatch.Handler = NULL;
1132
1133 /* Restore Method node (if any), set dispatch flags */
1134
1135 GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1136 GpeEventInfo->Flags &=
1137 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1138 GpeEventInfo->Flags |= Handler->OriginalFlags;
1139
1140 /*
1141 * If the GPE was previously associated with a method and it was
1142 * enabled, it should be enabled at this point to restore the
1143 * post-initialization configuration.
1144 */
1145 if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1146 ACPI_GPE_DISPATCH_METHOD) ||
1147 (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1148 ACPI_GPE_DISPATCH_NOTIFY)) &&
1149 Handler->OriginallyEnabled)
1150 {
1151 (void) AcpiEvAddGpeReference (GpeEventInfo);
1152 }
1153
1154 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1155 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1156
1157 /* Make sure all deferred GPE tasks are completed */
1158
1159 AcpiOsWaitEventsComplete ();
1160
1161 /* Now we can free the handler object */
1162
1163 ACPI_FREE (Handler);
1164 return_ACPI_STATUS (Status);
1165
1166 UnlockAndExit:
1167 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1168 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1169 return_ACPI_STATUS (Status);
1170 }
1171
ACPI_EXPORT_SYMBOL(AcpiRemoveGpeHandler)1172 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1173
1174
1175 /*******************************************************************************
1176 *
1177 * FUNCTION: AcpiAcquireGlobalLock
1178 *
1179 * PARAMETERS: Timeout - How long the caller is willing to wait
1180 * Handle - Where the handle to the lock is returned
1181 * (if acquired)
1182 *
1183 * RETURN: Status
1184 *
1185 * DESCRIPTION: Acquire the ACPI Global Lock
1186 *
1187 * Note: Allows callers with the same thread ID to acquire the global lock
1188 * multiple times. In other words, externally, the behavior of the global lock
1189 * is identical to an AML mutex. On the first acquire, a new handle is
1190 * returned. On any subsequent calls to acquire by the same thread, the same
1191 * handle is returned.
1192 *
1193 ******************************************************************************/
1194
1195 ACPI_STATUS
1196 AcpiAcquireGlobalLock (
1197 UINT16 Timeout,
1198 UINT32 *Handle)
1199 {
1200 ACPI_STATUS Status;
1201
1202
1203 if (!Handle)
1204 {
1205 return (AE_BAD_PARAMETER);
1206 }
1207
1208 /* Must lock interpreter to prevent race conditions */
1209
1210 AcpiExEnterInterpreter ();
1211
1212 Status = AcpiExAcquireMutexObject (Timeout,
1213 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1214
1215 if (ACPI_SUCCESS (Status))
1216 {
1217 /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1218
1219 *Handle = AcpiGbl_GlobalLockHandle;
1220 }
1221
1222 AcpiExExitInterpreter ();
1223 return (Status);
1224 }
1225
ACPI_EXPORT_SYMBOL(AcpiAcquireGlobalLock)1226 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1227
1228
1229 /*******************************************************************************
1230 *
1231 * FUNCTION: AcpiReleaseGlobalLock
1232 *
1233 * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock
1234 *
1235 * RETURN: Status
1236 *
1237 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1238 *
1239 ******************************************************************************/
1240
1241 ACPI_STATUS
1242 AcpiReleaseGlobalLock (
1243 UINT32 Handle)
1244 {
1245 ACPI_STATUS Status;
1246
1247
1248 if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1249 {
1250 return (AE_NOT_ACQUIRED);
1251 }
1252
1253 Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1254 return (Status);
1255 }
1256
1257 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1258
1259 #endif /* !ACPI_REDUCED_HARDWARE */
1260