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