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