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