]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/events/evxfgpe.c
Update to BIND 9.6.3, the latest from ISC on the 9.6 branch.
[FreeBSD/FreeBSD.git] / sys / contrib / dev / 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 - 2011, 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
45 #define __EVXFGPE_C__
46
47 #include <contrib/dev/acpica/include/acpi.h>
48 #include <contrib/dev/acpica/include/accommon.h>
49 #include <contrib/dev/acpica/include/acevents.h>
50 #include <contrib/dev/acpica/include/acnamesp.h>
51
52 #define _COMPONENT          ACPI_EVENTS
53         ACPI_MODULE_NAME    ("evxfgpe")
54
55
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
84
85     ACPI_FUNCTION_TRACE (AcpiUpdateGpes);
86
87
88     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
89     if (ACPI_FAILURE (Status))
90     {
91         return_ACPI_STATUS (Status);
92     }
93
94     if (AcpiGbl_AllGpesInitialized)
95     {
96         goto UnlockAndExit;
97     }
98
99     Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
100     if (ACPI_SUCCESS (Status))
101     {
102         AcpiGbl_AllGpesInitialized = TRUE;
103     }
104
105 UnlockAndExit:
106     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
107     return_ACPI_STATUS (Status);
108 }
109
110 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
111
112
113 /*******************************************************************************
114  *
115  * FUNCTION:    AcpiEnableGpe
116  *
117  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
118  *              GpeNumber           - GPE level within the GPE block
119  *
120  * RETURN:      Status
121  *
122  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
123  *              hardware-enabled.
124  *
125  ******************************************************************************/
126
127 ACPI_STATUS
128 AcpiEnableGpe (
129     ACPI_HANDLE             GpeDevice,
130     UINT32                  GpeNumber)
131 {
132     ACPI_STATUS             Status = AE_BAD_PARAMETER;
133     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
134     ACPI_CPU_FLAGS          Flags;
135
136
137     ACPI_FUNCTION_TRACE (AcpiEnableGpe);
138
139
140     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
141
142     /* Ensure that we have a valid GPE number */
143
144     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
145     if (GpeEventInfo)
146     {
147         Status = AcpiEvAddGpeReference (GpeEventInfo);
148     }
149
150     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
151     return_ACPI_STATUS (Status);
152 }
153
154 ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
155
156
157 /*******************************************************************************
158  *
159  * FUNCTION:    AcpiDisableGpe
160  *
161  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
162  *              GpeNumber           - GPE level within the GPE block
163  *
164  * RETURN:      Status
165  *
166  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
167  *              removed, only then is the GPE disabled (for runtime GPEs), or
168  *              the GPE mask bit disabled (for wake GPEs)
169  *
170  ******************************************************************************/
171
172 ACPI_STATUS
173 AcpiDisableGpe (
174     ACPI_HANDLE             GpeDevice,
175     UINT32                  GpeNumber)
176 {
177     ACPI_STATUS             Status = AE_BAD_PARAMETER;
178     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
179     ACPI_CPU_FLAGS          Flags;
180
181
182     ACPI_FUNCTION_TRACE (AcpiDisableGpe);
183
184
185     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
186
187     /* Ensure that we have a valid GPE number */
188
189     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
190     if (GpeEventInfo)
191     {
192         Status = AcpiEvRemoveGpeReference (GpeEventInfo);
193     }
194
195     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
196     return_ACPI_STATUS (Status);
197 }
198
199 ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
200
201
202 /*******************************************************************************
203  *
204  * FUNCTION:    AcpiSetGpe
205  *
206  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
207  *              GpeNumber           - GPE level within the GPE block
208  *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
209  *
210  * RETURN:      Status
211  *
212  * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
213  *              the reference count mechanism used in the AcpiEnableGpe and
214  *              AcpiDisableGpe interfaces -- and should be used with care.
215  *
216  * Note: Typically used to disable a runtime GPE for short period of time,
217  * then re-enable it, without disturbing the existing reference counts. This
218  * is useful, for example, in the Embedded Controller (EC) driver.
219  *
220  ******************************************************************************/
221
222 ACPI_STATUS
223 AcpiSetGpe (
224     ACPI_HANDLE             GpeDevice,
225     UINT32                  GpeNumber,
226     UINT8                   Action)
227 {
228     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
229     ACPI_STATUS             Status;
230     ACPI_CPU_FLAGS          Flags;
231
232
233     ACPI_FUNCTION_TRACE (AcpiSetGpe);
234
235
236     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
237
238     /* Ensure that we have a valid GPE number */
239
240     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
241     if (!GpeEventInfo)
242     {
243         Status = AE_BAD_PARAMETER;
244         goto UnlockAndExit;
245     }
246
247     /* Perform the action */
248
249     switch (Action)
250     {
251     case ACPI_GPE_ENABLE:
252         Status = AcpiEvEnableGpe (GpeEventInfo);
253         break;
254
255     case ACPI_GPE_DISABLE:
256         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
257         break;
258
259     default:
260         Status = AE_BAD_PARAMETER;
261         break;
262     }
263
264 UnlockAndExit:
265     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
266     return_ACPI_STATUS (Status);
267 }
268
269 ACPI_EXPORT_SYMBOL (AcpiSetGpe)
270
271
272 /*******************************************************************************
273  *
274  * FUNCTION:    AcpiSetupGpeForWake
275  *
276  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
277  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
278  *              GpeNumber           - GPE level within the GPE block
279  *
280  * RETURN:      Status
281  *
282  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
283  *              interface is intended to be used as the host executes the
284  *              _PRW methods (Power Resources for Wake) in the system tables.
285  *              Each _PRW appears under a Device Object (The WakeDevice), and
286  *              contains the info for the wake GPE associated with the
287  *              WakeDevice.
288  *
289  ******************************************************************************/
290
291 ACPI_STATUS
292 AcpiSetupGpeForWake (
293     ACPI_HANDLE             WakeDevice,
294     ACPI_HANDLE             GpeDevice,
295     UINT32                  GpeNumber)
296 {
297     ACPI_STATUS             Status = AE_BAD_PARAMETER;
298     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
299     ACPI_NAMESPACE_NODE     *DeviceNode;
300     ACPI_CPU_FLAGS          Flags;
301
302
303     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
304
305
306     /* Parameter Validation */
307
308     if (!WakeDevice)
309     {
310         /*
311          * By forcing WakeDevice to be valid, we automatically enable the
312          * implicit notify feature on all hosts.
313          */
314         return_ACPI_STATUS (AE_BAD_PARAMETER);
315     }
316
317     /* Validate WakeDevice is of type Device */
318
319     DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
320     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
321     {
322         return_ACPI_STATUS (AE_BAD_PARAMETER);
323     }
324
325     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
326
327     /* Ensure that we have a valid GPE number */
328
329     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
330     if (GpeEventInfo)
331     {
332         /*
333          * If there is no method or handler for this GPE, then the
334          * WakeDevice will be notified whenever this GPE fires (aka
335          * "implicit notify") Note: The GPE is assumed to be
336          * level-triggered (for windows compatibility).
337          */
338         if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
339                 ACPI_GPE_DISPATCH_NONE)
340         {
341             GpeEventInfo->Flags =
342                 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
343             GpeEventInfo->Dispatch.DeviceNode = DeviceNode;
344         }
345
346         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
347         Status = AE_OK;
348     }
349
350     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
351     return_ACPI_STATUS (Status);
352 }
353
354 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
355
356
357 /*******************************************************************************
358  *
359  * FUNCTION:    AcpiSetGpeWakeMask
360  *
361  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
362  *              GpeNumber           - GPE level within the GPE block
363  *              Action              - Enable or Disable
364  *
365  * RETURN:      Status
366  *
367  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
368  *              already be marked as a WAKE GPE.
369  *
370  ******************************************************************************/
371
372 ACPI_STATUS
373 AcpiSetGpeWakeMask (
374     ACPI_HANDLE             GpeDevice,
375     UINT32                  GpeNumber,
376     UINT8                   Action)
377 {
378     ACPI_STATUS             Status = AE_OK;
379     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
380     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
381     ACPI_CPU_FLAGS          Flags;
382     UINT32                  RegisterBit;
383
384
385     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
386
387
388     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
389
390     /*
391      * Ensure that we have a valid GPE number and that this GPE is in
392      * fact a wake GPE
393      */
394     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
395     if (!GpeEventInfo)
396     {
397         Status = AE_BAD_PARAMETER;
398         goto UnlockAndExit;
399     }
400
401     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
402     {
403         Status = AE_TYPE;
404         goto UnlockAndExit;
405     }
406
407     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
408     if (!GpeRegisterInfo)
409     {
410         Status = AE_NOT_EXIST;
411         goto UnlockAndExit;
412     }
413
414     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
415
416     /* Perform the action */
417
418     switch (Action)
419     {
420     case ACPI_GPE_ENABLE:
421         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
422         break;
423
424     case ACPI_GPE_DISABLE:
425         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
426         break;
427
428     default:
429         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
430         Status = AE_BAD_PARAMETER;
431         break;
432     }
433
434 UnlockAndExit:
435     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
436     return_ACPI_STATUS (Status);
437 }
438
439 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
440
441
442 /*******************************************************************************
443  *
444  * FUNCTION:    AcpiClearGpe
445  *
446  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
447  *              GpeNumber           - GPE level within the GPE block
448  *
449  * RETURN:      Status
450  *
451  * DESCRIPTION: Clear an ACPI event (general purpose)
452  *
453  ******************************************************************************/
454
455 ACPI_STATUS
456 AcpiClearGpe (
457     ACPI_HANDLE             GpeDevice,
458     UINT32                  GpeNumber)
459 {
460     ACPI_STATUS             Status = AE_OK;
461     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
462     ACPI_CPU_FLAGS          Flags;
463
464
465     ACPI_FUNCTION_TRACE (AcpiClearGpe);
466
467
468     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
469
470     /* Ensure that we have a valid GPE number */
471
472     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
473     if (!GpeEventInfo)
474     {
475         Status = AE_BAD_PARAMETER;
476         goto UnlockAndExit;
477     }
478
479     Status = AcpiHwClearGpe (GpeEventInfo);
480
481 UnlockAndExit:
482     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
483     return_ACPI_STATUS (Status);
484 }
485
486 ACPI_EXPORT_SYMBOL (AcpiClearGpe)
487
488
489 /*******************************************************************************
490  *
491  * FUNCTION:    AcpiGetGpeStatus
492  *
493  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
494  *              GpeNumber           - GPE level within the GPE block
495  *              EventStatus         - Where the current status of the event
496  *                                    will be returned
497  *
498  * RETURN:      Status
499  *
500  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
501  *
502  ******************************************************************************/
503
504 ACPI_STATUS
505 AcpiGetGpeStatus (
506     ACPI_HANDLE             GpeDevice,
507     UINT32                  GpeNumber,
508     ACPI_EVENT_STATUS       *EventStatus)
509 {
510     ACPI_STATUS             Status = AE_OK;
511     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
512     ACPI_CPU_FLAGS          Flags;
513
514
515     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
516
517
518     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
519
520     /* Ensure that we have a valid GPE number */
521
522     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
523     if (!GpeEventInfo)
524     {
525         Status = AE_BAD_PARAMETER;
526         goto UnlockAndExit;
527     }
528
529     /* Obtain status on the requested GPE number */
530
531     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
532
533 UnlockAndExit:
534     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
535     return_ACPI_STATUS (Status);
536 }
537
538 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
539
540
541 /*******************************************************************************
542  *
543  * FUNCTION:    AcpiFinishGpe
544  *
545  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
546  *                                    (NULL for FADT defined GPEs)
547  *              GpeNumber           - GPE level within the GPE block
548  *
549  * RETURN:      Status
550  *
551  * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
552  *              processing. Intended for use by asynchronous host-installed
553  *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
554  *              is set in the GPE info.
555  *
556  ******************************************************************************/
557
558 ACPI_STATUS
559 AcpiFinishGpe (
560     ACPI_HANDLE             GpeDevice,
561     UINT32                  GpeNumber)
562 {
563     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
564     ACPI_STATUS             Status;
565     ACPI_CPU_FLAGS          Flags;
566
567
568     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
569
570
571     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
572
573     /* Ensure that we have a valid GPE number */
574
575     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
576     if (!GpeEventInfo)
577     {
578         Status = AE_BAD_PARAMETER;
579         goto UnlockAndExit;
580     }
581
582     Status = AcpiEvFinishGpe (GpeEventInfo);
583
584 UnlockAndExit:
585     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
586     return_ACPI_STATUS (Status);
587 }
588
589 ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
590
591
592 /******************************************************************************
593  *
594  * FUNCTION:    AcpiDisableAllGpes
595  *
596  * PARAMETERS:  None
597  *
598  * RETURN:      Status
599  *
600  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
601  *
602  ******************************************************************************/
603
604 ACPI_STATUS
605 AcpiDisableAllGpes (
606     void)
607 {
608     ACPI_STATUS             Status;
609
610
611     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
612
613
614     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
615     if (ACPI_FAILURE (Status))
616     {
617         return_ACPI_STATUS (Status);
618     }
619
620     Status = AcpiHwDisableAllGpes ();
621     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
622
623     return_ACPI_STATUS (Status);
624 }
625
626 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
627
628
629 /******************************************************************************
630  *
631  * FUNCTION:    AcpiEnableAllRuntimeGpes
632  *
633  * PARAMETERS:  None
634  *
635  * RETURN:      Status
636  *
637  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
638  *
639  ******************************************************************************/
640
641 ACPI_STATUS
642 AcpiEnableAllRuntimeGpes (
643     void)
644 {
645     ACPI_STATUS             Status;
646
647
648     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
649
650
651     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
652     if (ACPI_FAILURE (Status))
653     {
654         return_ACPI_STATUS (Status);
655     }
656
657     Status = AcpiHwEnableAllRuntimeGpes ();
658     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
659
660     return_ACPI_STATUS (Status);
661 }
662
663 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
664
665
666 /*******************************************************************************
667  *
668  * FUNCTION:    AcpiInstallGpeBlock
669  *
670  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
671  *              GpeBlockAddress     - Address and SpaceID
672  *              RegisterCount       - Number of GPE register pairs in the block
673  *              InterruptNumber     - H/W interrupt for the block
674  *
675  * RETURN:      Status
676  *
677  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
678  *              enabled here.
679  *
680  ******************************************************************************/
681
682 ACPI_STATUS
683 AcpiInstallGpeBlock (
684     ACPI_HANDLE             GpeDevice,
685     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
686     UINT32                  RegisterCount,
687     UINT32                  InterruptNumber)
688 {
689     ACPI_STATUS             Status;
690     ACPI_OPERAND_OBJECT     *ObjDesc;
691     ACPI_NAMESPACE_NODE     *Node;
692     ACPI_GPE_BLOCK_INFO     *GpeBlock;
693
694
695     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
696
697
698     if ((!GpeDevice)       ||
699         (!GpeBlockAddress) ||
700         (!RegisterCount))
701     {
702         return_ACPI_STATUS (AE_BAD_PARAMETER);
703     }
704
705     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
706     if (ACPI_FAILURE (Status))
707     {
708         return (Status);
709     }
710
711     Node = AcpiNsValidateHandle (GpeDevice);
712     if (!Node)
713     {
714         Status = AE_BAD_PARAMETER;
715         goto UnlockAndExit;
716     }
717
718     /*
719      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
720      * is always zero
721      */
722     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,
723                 0, InterruptNumber, &GpeBlock);
724     if (ACPI_FAILURE (Status))
725     {
726         goto UnlockAndExit;
727     }
728
729     /* Install block in the DeviceObject attached to the node */
730
731     ObjDesc = AcpiNsGetAttachedObject (Node);
732     if (!ObjDesc)
733     {
734         /*
735          * No object, create a new one (Device nodes do not always have
736          * an attached object)
737          */
738         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
739         if (!ObjDesc)
740         {
741             Status = AE_NO_MEMORY;
742             goto UnlockAndExit;
743         }
744
745         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
746
747         /* Remove local reference to the object */
748
749         AcpiUtRemoveReference (ObjDesc);
750         if (ACPI_FAILURE (Status))
751         {
752             goto UnlockAndExit;
753         }
754     }
755
756     /* Now install the GPE block in the DeviceObject */
757
758     ObjDesc->Device.GpeBlock = GpeBlock;
759
760
761 UnlockAndExit:
762     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
763     return_ACPI_STATUS (Status);
764 }
765
766 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
767
768
769 /*******************************************************************************
770  *
771  * FUNCTION:    AcpiRemoveGpeBlock
772  *
773  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
774  *
775  * RETURN:      Status
776  *
777  * DESCRIPTION: Remove a previously installed block of GPE registers
778  *
779  ******************************************************************************/
780
781 ACPI_STATUS
782 AcpiRemoveGpeBlock (
783     ACPI_HANDLE             GpeDevice)
784 {
785     ACPI_OPERAND_OBJECT     *ObjDesc;
786     ACPI_STATUS             Status;
787     ACPI_NAMESPACE_NODE     *Node;
788
789
790     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
791
792
793     if (!GpeDevice)
794     {
795         return_ACPI_STATUS (AE_BAD_PARAMETER);
796     }
797
798     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
799     if (ACPI_FAILURE (Status))
800     {
801         return (Status);
802     }
803
804     Node = AcpiNsValidateHandle (GpeDevice);
805     if (!Node)
806     {
807         Status = AE_BAD_PARAMETER;
808         goto UnlockAndExit;
809     }
810
811     /* Get the DeviceObject attached to the node */
812
813     ObjDesc = AcpiNsGetAttachedObject (Node);
814     if (!ObjDesc ||
815         !ObjDesc->Device.GpeBlock)
816     {
817         return_ACPI_STATUS (AE_NULL_OBJECT);
818     }
819
820     /* Delete the GPE block (but not the DeviceObject) */
821
822     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
823     if (ACPI_SUCCESS (Status))
824     {
825         ObjDesc->Device.GpeBlock = NULL;
826     }
827
828 UnlockAndExit:
829     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
830     return_ACPI_STATUS (Status);
831 }
832
833 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
834
835
836 /*******************************************************************************
837  *
838  * FUNCTION:    AcpiGetGpeDevice
839  *
840  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
841  *              GpeDevice           - Where the parent GPE Device is returned
842  *
843  * RETURN:      Status
844  *
845  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
846  *              gpe device indicates that the gpe number is contained in one of
847  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
848  *
849  ******************************************************************************/
850
851 ACPI_STATUS
852 AcpiGetGpeDevice (
853     UINT32                  Index,
854     ACPI_HANDLE             *GpeDevice)
855 {
856     ACPI_GPE_DEVICE_INFO    Info;
857     ACPI_STATUS             Status;
858
859
860     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
861
862
863     if (!GpeDevice)
864     {
865         return_ACPI_STATUS (AE_BAD_PARAMETER);
866     }
867
868     if (Index >= AcpiCurrentGpeCount)
869     {
870         return_ACPI_STATUS (AE_NOT_EXIST);
871     }
872
873     /* Setup and walk the GPE list */
874
875     Info.Index = Index;
876     Info.Status = AE_NOT_EXIST;
877     Info.GpeDevice = NULL;
878     Info.NextBlockBaseIndex = 0;
879
880     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
881     if (ACPI_FAILURE (Status))
882     {
883         return_ACPI_STATUS (Status);
884     }
885
886     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
887     return_ACPI_STATUS (Info.Status);
888 }
889
890 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)