f56aa1d9bb44b1bba5ac64a9dbb9202c1a07eb38
[reactos.git] / drivers / bus / acpi / acpica / events / evxfgpe.c
1 /******************************************************************************
2 *
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2019, 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 "acevents.h"
49 #include "acnamesp.h"
50
51 #define _COMPONENT ACPI_EVENTS
52 ACPI_MODULE_NAME ("evxfgpe")
53
54
55 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56 /*******************************************************************************
57 *
58 * FUNCTION: AcpiUpdateAllGpes
59 *
60 * PARAMETERS: None
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65 * associated _Lxx or _Exx methods and are not pointed to by any
66 * device _PRW methods (this indicates that these GPEs are
67 * generally intended for system or device wakeup. Such GPEs
68 * have to be enabled directly when the devices whose _PRW
69 * methods point to them are set up for wakeup signaling.)
70 *
71 * NOTE: Should be called after any GPEs are added to the system. Primarily,
72 * after the system _PRW methods have been run, but also after a GPE Block
73 * Device has been added or if any new GPE methods have been added via a
74 * dynamic table load.
75 *
76 ******************************************************************************/
77
78 ACPI_STATUS
79 AcpiUpdateAllGpes (
80 void)
81 {
82 ACPI_STATUS Status;
83 BOOLEAN IsPollingNeeded = FALSE;
84
85
86 ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
87
88
89 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
90 if (ACPI_FAILURE (Status))
91 {
92 return_ACPI_STATUS (Status);
93 }
94
95 if (AcpiGbl_AllGpesInitialized)
96 {
97 goto UnlockAndExit;
98 }
99
100 Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock,
101 &IsPollingNeeded);
102 if (ACPI_SUCCESS (Status))
103 {
104 AcpiGbl_AllGpesInitialized = TRUE;
105 }
106
107 UnlockAndExit:
108 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
109
110 if (IsPollingNeeded && AcpiGbl_AllGpesInitialized)
111 {
112 /* Poll GPEs to handle already triggered events */
113
114 AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead);
115 }
116 return_ACPI_STATUS (Status);
117 }
118
119 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
120
121
122 /*******************************************************************************
123 *
124 * FUNCTION: AcpiEnableGpe
125 *
126 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
127 * GpeNumber - GPE level within the GPE block
128 *
129 * RETURN: Status
130 *
131 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
132 * hardware-enabled.
133 *
134 ******************************************************************************/
135
136 ACPI_STATUS
137 AcpiEnableGpe (
138 ACPI_HANDLE GpeDevice,
139 UINT32 GpeNumber)
140 {
141 ACPI_STATUS Status = AE_BAD_PARAMETER;
142 ACPI_GPE_EVENT_INFO *GpeEventInfo;
143 ACPI_CPU_FLAGS Flags;
144
145
146 ACPI_FUNCTION_TRACE (AcpiEnableGpe);
147
148
149 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
150
151 /*
152 * Ensure that we have a valid GPE number and that there is some way
153 * of handling the GPE (handler or a GPE method). In other words, we
154 * won't allow a valid GPE to be enabled if there is no way to handle it.
155 */
156 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
157 if (GpeEventInfo)
158 {
159 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
160 ACPI_GPE_DISPATCH_NONE)
161 {
162 Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE);
163 if (ACPI_SUCCESS (Status) &&
164 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))
165 {
166 /* Poll edge-triggered GPEs to handle existing events */
167
168 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
169 (void) AcpiEvDetectGpe (
170 GpeDevice, GpeEventInfo, GpeNumber);
171 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
172 }
173 }
174 else
175 {
176 Status = AE_NO_HANDLER;
177 }
178 }
179
180 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
181 return_ACPI_STATUS (Status);
182 }
183
184 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
185
186
187 /*******************************************************************************
188 *
189 * FUNCTION: AcpiDisableGpe
190 *
191 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
192 * GpeNumber - GPE level within the GPE block
193 *
194 * RETURN: Status
195 *
196 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
197 * removed, only then is the GPE disabled (for runtime GPEs), or
198 * the GPE mask bit disabled (for wake GPEs)
199 *
200 ******************************************************************************/
201
202 ACPI_STATUS
203 AcpiDisableGpe (
204 ACPI_HANDLE GpeDevice,
205 UINT32 GpeNumber)
206 {
207 ACPI_STATUS Status = AE_BAD_PARAMETER;
208 ACPI_GPE_EVENT_INFO *GpeEventInfo;
209 ACPI_CPU_FLAGS Flags;
210
211
212 ACPI_FUNCTION_TRACE (AcpiDisableGpe);
213
214
215 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
216
217 /* Ensure that we have a valid GPE number */
218
219 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
220 if (GpeEventInfo)
221 {
222 Status = AcpiEvRemoveGpeReference (GpeEventInfo);
223 }
224
225 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
226 return_ACPI_STATUS (Status);
227 }
228
229 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
230
231
232 /*******************************************************************************
233 *
234 * FUNCTION: AcpiSetGpe
235 *
236 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
237 * GpeNumber - GPE level within the GPE block
238 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
239 *
240 * RETURN: Status
241 *
242 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
243 * the reference count mechanism used in the AcpiEnableGpe(),
244 * AcpiDisableGpe() interfaces.
245 * This API is typically used by the GPE raw handler mode driver
246 * to switch between the polling mode and the interrupt mode after
247 * the driver has enabled the GPE.
248 * The APIs should be invoked in this order:
249 * AcpiEnableGpe() <- Ensure the reference count > 0
250 * AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
251 * AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode
252 * AcpiDisableGpe() <- Decrease the reference count
253 *
254 * Note: If a GPE is shared by 2 silicon components, then both the drivers
255 * should support GPE polling mode or disabling the GPE for long period
256 * for one driver may break the other. So use it with care since all
257 * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
258 *
259 ******************************************************************************/
260
261 ACPI_STATUS
262 AcpiSetGpe (
263 ACPI_HANDLE GpeDevice,
264 UINT32 GpeNumber,
265 UINT8 Action)
266 {
267 ACPI_GPE_EVENT_INFO *GpeEventInfo;
268 ACPI_STATUS Status;
269 ACPI_CPU_FLAGS Flags;
270
271
272 ACPI_FUNCTION_TRACE (AcpiSetGpe);
273
274
275 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
276
277 /* Ensure that we have a valid GPE number */
278
279 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
280 if (!GpeEventInfo)
281 {
282 Status = AE_BAD_PARAMETER;
283 goto UnlockAndExit;
284 }
285
286 /* Perform the action */
287
288 switch (Action)
289 {
290 case ACPI_GPE_ENABLE:
291
292 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
293 GpeEventInfo->DisableForDispatch = FALSE;
294 break;
295
296 case ACPI_GPE_DISABLE:
297
298 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
299 GpeEventInfo->DisableForDispatch = TRUE;
300 break;
301
302 default:
303
304 Status = AE_BAD_PARAMETER;
305 break;
306 }
307
308 UnlockAndExit:
309 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
310 return_ACPI_STATUS (Status);
311 }
312
313 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
314
315
316 /*******************************************************************************
317 *
318 * FUNCTION: AcpiMaskGpe
319 *
320 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
321 * GpeNumber - GPE level within the GPE block
322 * IsMasked - Whether the GPE is masked or not
323 *
324 * RETURN: Status
325 *
326 * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
327 * prevent a GPE flooding.
328 *
329 ******************************************************************************/
330
331 ACPI_STATUS
332 AcpiMaskGpe (
333 ACPI_HANDLE GpeDevice,
334 UINT32 GpeNumber,
335 BOOLEAN IsMasked)
336 {
337 ACPI_GPE_EVENT_INFO *GpeEventInfo;
338 ACPI_STATUS Status;
339 ACPI_CPU_FLAGS Flags;
340
341
342 ACPI_FUNCTION_TRACE (AcpiMaskGpe);
343
344
345 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
346
347 /* Ensure that we have a valid GPE number */
348
349 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
350 if (!GpeEventInfo)
351 {
352 Status = AE_BAD_PARAMETER;
353 goto UnlockAndExit;
354 }
355
356 Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);
357
358 UnlockAndExit:
359 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
360 return_ACPI_STATUS (Status);
361 }
362
363 ACPI_EXPORT_SYMBOL (AcpiMaskGpe)
364
365
366 /*******************************************************************************
367 *
368 * FUNCTION: AcpiMarkGpeForWake
369 *
370 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
371 * GpeNumber - GPE level within the GPE block
372 *
373 * RETURN: Status
374 *
375 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
376 * sets the ACPI_GPE_CAN_WAKE flag.
377 *
378 * Some potential callers of AcpiSetupGpeForWake may know in advance that
379 * there won't be any notify handlers installed for device wake notifications
380 * from the given GPE (one example is a button GPE in Linux). For these cases,
381 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
382 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
383 * setup implicit wake notification for it (since there's no handler method).
384 *
385 ******************************************************************************/
386
387 ACPI_STATUS
388 AcpiMarkGpeForWake (
389 ACPI_HANDLE GpeDevice,
390 UINT32 GpeNumber)
391 {
392 ACPI_GPE_EVENT_INFO *GpeEventInfo;
393 ACPI_STATUS Status = AE_BAD_PARAMETER;
394 ACPI_CPU_FLAGS Flags;
395
396
397 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
398
399
400 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
401
402 /* Ensure that we have a valid GPE number */
403
404 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
405 if (GpeEventInfo)
406 {
407 /* Mark the GPE as a possible wake event */
408
409 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
410 Status = AE_OK;
411 }
412
413 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
414 return_ACPI_STATUS (Status);
415 }
416
417 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
418
419
420 /*******************************************************************************
421 *
422 * FUNCTION: AcpiSetupGpeForWake
423 *
424 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW)
425 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
426 * GpeNumber - GPE level within the GPE block
427 *
428 * RETURN: Status
429 *
430 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
431 * interface is intended to be used as the host executes the
432 * _PRW methods (Power Resources for Wake) in the system tables.
433 * Each _PRW appears under a Device Object (The WakeDevice), and
434 * contains the info for the wake GPE associated with the
435 * WakeDevice.
436 *
437 ******************************************************************************/
438
439 ACPI_STATUS
440 AcpiSetupGpeForWake (
441 ACPI_HANDLE WakeDevice,
442 ACPI_HANDLE GpeDevice,
443 UINT32 GpeNumber)
444 {
445 ACPI_STATUS Status;
446 ACPI_GPE_EVENT_INFO *GpeEventInfo;
447 ACPI_NAMESPACE_NODE *DeviceNode;
448 ACPI_GPE_NOTIFY_INFO *Notify;
449 ACPI_GPE_NOTIFY_INFO *NewNotify;
450 ACPI_CPU_FLAGS Flags;
451
452
453 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
454
455
456 /* Parameter Validation */
457
458 if (!WakeDevice)
459 {
460 /*
461 * By forcing WakeDevice to be valid, we automatically enable the
462 * implicit notify feature on all hosts.
463 */
464 return_ACPI_STATUS (AE_BAD_PARAMETER);
465 }
466
467 /* Handle root object case */
468
469 if (WakeDevice == ACPI_ROOT_OBJECT)
470 {
471 DeviceNode = AcpiGbl_RootNode;
472 }
473 else
474 {
475 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
476 }
477
478 /* Validate WakeDevice is of type Device */
479
480 if (DeviceNode->Type != ACPI_TYPE_DEVICE)
481 {
482 return_ACPI_STATUS (AE_BAD_PARAMETER);
483 }
484
485 /*
486 * Allocate a new notify object up front, in case it is needed.
487 * Memory allocation while holding a spinlock is a big no-no
488 * on some hosts.
489 */
490 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
491 if (!NewNotify)
492 {
493 return_ACPI_STATUS (AE_NO_MEMORY);
494 }
495
496 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
497
498 /* Ensure that we have a valid GPE number */
499
500 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
501 if (!GpeEventInfo)
502 {
503 Status = AE_BAD_PARAMETER;
504 goto UnlockAndExit;
505 }
506
507 /*
508 * If there is no method or handler for this GPE, then the
509 * WakeDevice will be notified whenever this GPE fires. This is
510 * known as an "implicit notify". Note: The GPE is assumed to be
511 * level-triggered (for windows compatibility).
512 */
513 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
514 ACPI_GPE_DISPATCH_NONE)
515 {
516 /*
517 * This is the first device for implicit notify on this GPE.
518 * Just set the flags here, and enter the NOTIFY block below.
519 */
520 GpeEventInfo->Flags =
521 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
522 }
523 else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)
524 {
525 /*
526 * A reference to this GPE has been added during the GPE block
527 * initialization, so drop it now to prevent the GPE from being
528 * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
529 */
530 (void) AcpiEvRemoveGpeReference (GpeEventInfo);
531 GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED;
532 }
533
534 /*
535 * If we already have an implicit notify on this GPE, add
536 * this device to the notify list.
537 */
538 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
539 ACPI_GPE_DISPATCH_NOTIFY)
540 {
541 /* Ensure that the device is not already in the list */
542
543 Notify = GpeEventInfo->Dispatch.NotifyList;
544 while (Notify)
545 {
546 if (Notify->DeviceNode == DeviceNode)
547 {
548 Status = AE_ALREADY_EXISTS;
549 goto UnlockAndExit;
550 }
551 Notify = Notify->Next;
552 }
553
554 /* Add this device to the notify list for this GPE */
555
556 NewNotify->DeviceNode = DeviceNode;
557 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
558 GpeEventInfo->Dispatch.NotifyList = NewNotify;
559 NewNotify = NULL;
560 }
561
562 /* Mark the GPE as a possible wake event */
563
564 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
565 Status = AE_OK;
566
567
568 UnlockAndExit:
569 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
570
571 /* Delete the notify object if it was not used above */
572
573 if (NewNotify)
574 {
575 ACPI_FREE (NewNotify);
576 }
577 return_ACPI_STATUS (Status);
578 }
579
580 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
581
582
583 /*******************************************************************************
584 *
585 * FUNCTION: AcpiSetGpeWakeMask
586 *
587 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
588 * GpeNumber - GPE level within the GPE block
589 * Action - Enable or Disable
590 *
591 * RETURN: Status
592 *
593 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
594 * already be marked as a WAKE GPE.
595 *
596 ******************************************************************************/
597
598 ACPI_STATUS
599 AcpiSetGpeWakeMask (
600 ACPI_HANDLE GpeDevice,
601 UINT32 GpeNumber,
602 UINT8 Action)
603 {
604 ACPI_STATUS Status = AE_OK;
605 ACPI_GPE_EVENT_INFO *GpeEventInfo;
606 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
607 ACPI_CPU_FLAGS Flags;
608 UINT32 RegisterBit;
609
610
611 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
612
613
614 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
615
616 /*
617 * Ensure that we have a valid GPE number and that this GPE is in
618 * fact a wake GPE
619 */
620 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
621 if (!GpeEventInfo)
622 {
623 Status = AE_BAD_PARAMETER;
624 goto UnlockAndExit;
625 }
626
627 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
628 {
629 Status = AE_TYPE;
630 goto UnlockAndExit;
631 }
632
633 GpeRegisterInfo = GpeEventInfo->RegisterInfo;
634 if (!GpeRegisterInfo)
635 {
636 Status = AE_NOT_EXIST;
637 goto UnlockAndExit;
638 }
639
640 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
641
642 /* Perform the action */
643
644 switch (Action)
645 {
646 case ACPI_GPE_ENABLE:
647
648 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
649 break;
650
651 case ACPI_GPE_DISABLE:
652
653 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
654 break;
655
656 default:
657
658 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
659 Status = AE_BAD_PARAMETER;
660 break;
661 }
662
663 UnlockAndExit:
664 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
665 return_ACPI_STATUS (Status);
666 }
667
668 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
669
670
671 /*******************************************************************************
672 *
673 * FUNCTION: AcpiClearGpe
674 *
675 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
676 * GpeNumber - GPE level within the GPE block
677 *
678 * RETURN: Status
679 *
680 * DESCRIPTION: Clear an ACPI event (general purpose)
681 *
682 ******************************************************************************/
683
684 ACPI_STATUS
685 AcpiClearGpe (
686 ACPI_HANDLE GpeDevice,
687 UINT32 GpeNumber)
688 {
689 ACPI_STATUS Status = AE_OK;
690 ACPI_GPE_EVENT_INFO *GpeEventInfo;
691 ACPI_CPU_FLAGS Flags;
692
693
694 ACPI_FUNCTION_TRACE (AcpiClearGpe);
695
696
697 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
698
699 /* Ensure that we have a valid GPE number */
700
701 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702 if (!GpeEventInfo)
703 {
704 Status = AE_BAD_PARAMETER;
705 goto UnlockAndExit;
706 }
707
708 Status = AcpiHwClearGpe (GpeEventInfo);
709
710 UnlockAndExit:
711 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
712 return_ACPI_STATUS (Status);
713 }
714
715 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
716
717
718 /*******************************************************************************
719 *
720 * FUNCTION: AcpiGetGpeStatus
721 *
722 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
723 * GpeNumber - GPE level within the GPE block
724 * EventStatus - Where the current status of the event
725 * will be returned
726 *
727 * RETURN: Status
728 *
729 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
730 *
731 ******************************************************************************/
732
733 ACPI_STATUS
734 AcpiGetGpeStatus (
735 ACPI_HANDLE GpeDevice,
736 UINT32 GpeNumber,
737 ACPI_EVENT_STATUS *EventStatus)
738 {
739 ACPI_STATUS Status = AE_OK;
740 ACPI_GPE_EVENT_INFO *GpeEventInfo;
741 ACPI_CPU_FLAGS Flags;
742
743
744 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
745
746
747 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
748
749 /* Ensure that we have a valid GPE number */
750
751 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
752 if (!GpeEventInfo)
753 {
754 Status = AE_BAD_PARAMETER;
755 goto UnlockAndExit;
756 }
757
758 /* Obtain status on the requested GPE number */
759
760 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
761
762 UnlockAndExit:
763 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
764 return_ACPI_STATUS (Status);
765 }
766
767 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
768
769
770 /*******************************************************************************
771 *
772 * FUNCTION: AcpiFinishGpe
773 *
774 * PARAMETERS: GpeDevice - Namespace node for the GPE Block
775 * (NULL for FADT defined GPEs)
776 * GpeNumber - GPE level within the GPE block
777 *
778 * RETURN: Status
779 *
780 * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
781 * processing. Intended for use by asynchronous host-installed
782 * GPE handlers. The GPE is only re-enabled if the EnableForRun bit
783 * is set in the GPE info.
784 *
785 ******************************************************************************/
786
787 ACPI_STATUS
788 AcpiFinishGpe (
789 ACPI_HANDLE GpeDevice,
790 UINT32 GpeNumber)
791 {
792 ACPI_GPE_EVENT_INFO *GpeEventInfo;
793 ACPI_STATUS Status;
794 ACPI_CPU_FLAGS Flags;
795
796
797 ACPI_FUNCTION_TRACE (AcpiFinishGpe);
798
799
800 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
801
802 /* Ensure that we have a valid GPE number */
803
804 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
805 if (!GpeEventInfo)
806 {
807 Status = AE_BAD_PARAMETER;
808 goto UnlockAndExit;
809 }
810
811 Status = AcpiEvFinishGpe (GpeEventInfo);
812
813 UnlockAndExit:
814 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
815 return_ACPI_STATUS (Status);
816 }
817
818 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
819
820
821 /******************************************************************************
822 *
823 * FUNCTION: AcpiDisableAllGpes
824 *
825 * PARAMETERS: None
826 *
827 * RETURN: Status
828 *
829 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
830 *
831 ******************************************************************************/
832
833 ACPI_STATUS
834 AcpiDisableAllGpes (
835 void)
836 {
837 ACPI_STATUS Status;
838
839
840 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
841
842
843 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
844 if (ACPI_FAILURE (Status))
845 {
846 return_ACPI_STATUS (Status);
847 }
848
849 Status = AcpiHwDisableAllGpes ();
850 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
851
852 return_ACPI_STATUS (Status);
853 }
854
855 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
856
857
858 /******************************************************************************
859 *
860 * FUNCTION: AcpiEnableAllRuntimeGpes
861 *
862 * PARAMETERS: None
863 *
864 * RETURN: Status
865 *
866 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
867 *
868 ******************************************************************************/
869
870 ACPI_STATUS
871 AcpiEnableAllRuntimeGpes (
872 void)
873 {
874 ACPI_STATUS Status;
875
876
877 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
878
879
880 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
881 if (ACPI_FAILURE (Status))
882 {
883 return_ACPI_STATUS (Status);
884 }
885
886 Status = AcpiHwEnableAllRuntimeGpes ();
887 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
888
889 return_ACPI_STATUS (Status);
890 }
891
892 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
893
894
895 /******************************************************************************
896 *
897 * FUNCTION: AcpiEnableAllWakeupGpes
898 *
899 * PARAMETERS: None
900 *
901 * RETURN: Status
902 *
903 * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
904 * all GPE blocks.
905 *
906 ******************************************************************************/
907
908 ACPI_STATUS
909 AcpiEnableAllWakeupGpes (
910 void)
911 {
912 ACPI_STATUS Status;
913
914
915 ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
916
917
918 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
919 if (ACPI_FAILURE (Status))
920 {
921 return_ACPI_STATUS (Status);
922 }
923
924 Status = AcpiHwEnableAllWakeupGpes ();
925 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
926
927 return_ACPI_STATUS (Status);
928 }
929
930 ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
931
932
933 /*******************************************************************************
934 *
935 * FUNCTION: AcpiInstallGpeBlock
936 *
937 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
938 * GpeBlockAddress - Address and SpaceID
939 * RegisterCount - Number of GPE register pairs in the block
940 * InterruptNumber - H/W interrupt for the block
941 *
942 * RETURN: Status
943 *
944 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
945 * enabled here.
946 *
947 ******************************************************************************/
948
949 ACPI_STATUS
950 AcpiInstallGpeBlock (
951 ACPI_HANDLE GpeDevice,
952 ACPI_GENERIC_ADDRESS *GpeBlockAddress,
953 UINT32 RegisterCount,
954 UINT32 InterruptNumber)
955 {
956 ACPI_STATUS Status;
957 ACPI_OPERAND_OBJECT *ObjDesc;
958 ACPI_NAMESPACE_NODE *Node;
959 ACPI_GPE_BLOCK_INFO *GpeBlock;
960
961
962 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
963
964
965 if ((!GpeDevice) ||
966 (!GpeBlockAddress) ||
967 (!RegisterCount))
968 {
969 return_ACPI_STATUS (AE_BAD_PARAMETER);
970 }
971
972 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
973 if (ACPI_FAILURE (Status))
974 {
975 return_ACPI_STATUS (Status);
976 }
977
978 Node = AcpiNsValidateHandle (GpeDevice);
979 if (!Node)
980 {
981 Status = AE_BAD_PARAMETER;
982 goto UnlockAndExit;
983 }
984
985 /* Validate the parent device */
986
987 if (Node->Type != ACPI_TYPE_DEVICE)
988 {
989 Status = AE_TYPE;
990 goto UnlockAndExit;
991 }
992
993 if (Node->Object)
994 {
995 Status = AE_ALREADY_EXISTS;
996 goto UnlockAndExit;
997 }
998
999 /*
1000 * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1001 * is always zero
1002 */
1003 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1004 GpeBlockAddress->SpaceId, RegisterCount,
1005 0, InterruptNumber, &GpeBlock);
1006 if (ACPI_FAILURE (Status))
1007 {
1008 goto UnlockAndExit;
1009 }
1010
1011 /* Install block in the DeviceObject attached to the node */
1012
1013 ObjDesc = AcpiNsGetAttachedObject (Node);
1014 if (!ObjDesc)
1015 {
1016 /*
1017 * No object, create a new one (Device nodes do not always have
1018 * an attached object)
1019 */
1020 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1021 if (!ObjDesc)
1022 {
1023 Status = AE_NO_MEMORY;
1024 goto UnlockAndExit;
1025 }
1026
1027 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1028
1029 /* Remove local reference to the object */
1030
1031 AcpiUtRemoveReference (ObjDesc);
1032 if (ACPI_FAILURE (Status))
1033 {
1034 goto UnlockAndExit;
1035 }
1036 }
1037
1038 /* Now install the GPE block in the DeviceObject */
1039
1040 ObjDesc->Device.GpeBlock = GpeBlock;
1041
1042
1043 UnlockAndExit:
1044 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1045 return_ACPI_STATUS (Status);
1046 }
1047
1048 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1049
1050
1051 /*******************************************************************************
1052 *
1053 * FUNCTION: AcpiRemoveGpeBlock
1054 *
1055 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
1056 *
1057 * RETURN: Status
1058 *
1059 * DESCRIPTION: Remove a previously installed block of GPE registers
1060 *
1061 ******************************************************************************/
1062
1063 ACPI_STATUS
1064 AcpiRemoveGpeBlock (
1065 ACPI_HANDLE GpeDevice)
1066 {
1067 ACPI_OPERAND_OBJECT *ObjDesc;
1068 ACPI_STATUS Status;
1069 ACPI_NAMESPACE_NODE *Node;
1070
1071
1072 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1073
1074
1075 if (!GpeDevice)
1076 {
1077 return_ACPI_STATUS (AE_BAD_PARAMETER);
1078 }
1079
1080 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1081 if (ACPI_FAILURE (Status))
1082 {
1083 return_ACPI_STATUS (Status);
1084 }
1085
1086 Node = AcpiNsValidateHandle (GpeDevice);
1087 if (!Node)
1088 {
1089 Status = AE_BAD_PARAMETER;
1090 goto UnlockAndExit;
1091 }
1092
1093 /* Validate the parent device */
1094
1095 if (Node->Type != ACPI_TYPE_DEVICE)
1096 {
1097 Status = AE_TYPE;
1098 goto UnlockAndExit;
1099 }
1100
1101 /* Get the DeviceObject attached to the node */
1102
1103 ObjDesc = AcpiNsGetAttachedObject (Node);
1104 if (!ObjDesc ||
1105 !ObjDesc->Device.GpeBlock)
1106 {
1107 return_ACPI_STATUS (AE_NULL_OBJECT);
1108 }
1109
1110 /* Delete the GPE block (but not the DeviceObject) */
1111
1112 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1113 if (ACPI_SUCCESS (Status))
1114 {
1115 ObjDesc->Device.GpeBlock = NULL;
1116 }
1117
1118 UnlockAndExit:
1119 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1120 return_ACPI_STATUS (Status);
1121 }
1122
1123 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1124
1125
1126 /*******************************************************************************
1127 *
1128 * FUNCTION: AcpiGetGpeDevice
1129 *
1130 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount)
1131 * GpeDevice - Where the parent GPE Device is returned
1132 *
1133 * RETURN: Status
1134 *
1135 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1136 * gpe device indicates that the gpe number is contained in one of
1137 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
1138 *
1139 ******************************************************************************/
1140
1141 ACPI_STATUS
1142 AcpiGetGpeDevice (
1143 UINT32 Index,
1144 ACPI_HANDLE *GpeDevice)
1145 {
1146 ACPI_GPE_DEVICE_INFO Info;
1147 ACPI_STATUS Status;
1148
1149
1150 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1151
1152
1153 if (!GpeDevice)
1154 {
1155 return_ACPI_STATUS (AE_BAD_PARAMETER);
1156 }
1157
1158 if (Index >= AcpiCurrentGpeCount)
1159 {
1160 return_ACPI_STATUS (AE_NOT_EXIST);
1161 }
1162
1163 /* Setup and walk the GPE list */
1164
1165 Info.Index = Index;
1166 Info.Status = AE_NOT_EXIST;
1167 Info.GpeDevice = NULL;
1168 Info.NextBlockBaseIndex = 0;
1169
1170 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1171 if (ACPI_FAILURE (Status))
1172 {
1173 return_ACPI_STATUS (Status);
1174 }
1175
1176 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1177 return_ACPI_STATUS (Info.Status);
1178 }
1179
1180 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1181
1182 #endif /* !ACPI_REDUCED_HARDWARE */