xref: /titanic_52/usr/src/uts/intel/io/acpica/events/evgpeblk.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
1ae115bc7Smrj /******************************************************************************
2ae115bc7Smrj  *
3ae115bc7Smrj  * Module Name: evgpeblk - GPE block creation and initialization.
4ae115bc7Smrj  *
5ae115bc7Smrj  *****************************************************************************/
6ae115bc7Smrj 
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj  * All rights reserved.
10ae115bc7Smrj  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
25ae115bc7Smrj  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
29ae115bc7Smrj  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
43ae115bc7Smrj 
44ae115bc7Smrj #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46ae115bc7Smrj #include "acevents.h"
47ae115bc7Smrj #include "acnamesp.h"
48ae115bc7Smrj 
49ae115bc7Smrj #define _COMPONENT          ACPI_EVENTS
50ae115bc7Smrj         ACPI_MODULE_NAME    ("evgpeblk")
51ae115bc7Smrj 
52*385cc6b4SJerry Jelinek #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
53*385cc6b4SJerry Jelinek 
54ae115bc7Smrj /* Local prototypes */
55ae115bc7Smrj 
56ae115bc7Smrj static ACPI_STATUS
57ae115bc7Smrj AcpiEvInstallGpeBlock (
58ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock,
59ae115bc7Smrj     UINT32                  InterruptNumber);
60ae115bc7Smrj 
61ae115bc7Smrj static ACPI_STATUS
62ae115bc7Smrj AcpiEvCreateGpeInfoBlocks (
63ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock);
64ae115bc7Smrj 
65ae115bc7Smrj 
66ae115bc7Smrj /*******************************************************************************
67ae115bc7Smrj  *
68ae115bc7Smrj  * FUNCTION:    AcpiEvInstallGpeBlock
69ae115bc7Smrj  *
70ae115bc7Smrj  * PARAMETERS:  GpeBlock                - New GPE block
71aa2aa9a6SDana Myers  *              InterruptNumber         - Xrupt to be associated with this
72aa2aa9a6SDana Myers  *                                        GPE block
73ae115bc7Smrj  *
74ae115bc7Smrj  * RETURN:      Status
75ae115bc7Smrj  *
76ae115bc7Smrj  * DESCRIPTION: Install new GPE block with mutex support
77ae115bc7Smrj  *
78ae115bc7Smrj  ******************************************************************************/
79ae115bc7Smrj 
80ae115bc7Smrj static ACPI_STATUS
81ae115bc7Smrj AcpiEvInstallGpeBlock (
82ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock,
83ae115bc7Smrj     UINT32                  InterruptNumber)
84ae115bc7Smrj {
85ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *NextGpeBlock;
86ae115bc7Smrj     ACPI_GPE_XRUPT_INFO     *GpeXruptBlock;
87ae115bc7Smrj     ACPI_STATUS             Status;
88ae115bc7Smrj     ACPI_CPU_FLAGS          Flags;
89ae115bc7Smrj 
90ae115bc7Smrj 
91ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvInstallGpeBlock);
92ae115bc7Smrj 
93ae115bc7Smrj 
94ae115bc7Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
95ae115bc7Smrj     if (ACPI_FAILURE (Status))
96ae115bc7Smrj     {
97ae115bc7Smrj         return_ACPI_STATUS (Status);
98ae115bc7Smrj     }
99ae115bc7Smrj 
100*385cc6b4SJerry Jelinek     Status = AcpiEvGetGpeXruptBlock (InterruptNumber, &GpeXruptBlock);
101*385cc6b4SJerry Jelinek     if (ACPI_FAILURE (Status))
102ae115bc7Smrj     {
103ae115bc7Smrj         goto UnlockAndExit;
104ae115bc7Smrj     }
105ae115bc7Smrj 
106ae115bc7Smrj     /* Install the new block at the end of the list with lock */
107ae115bc7Smrj 
108ae115bc7Smrj     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
109ae115bc7Smrj     if (GpeXruptBlock->GpeBlockListHead)
110ae115bc7Smrj     {
111ae115bc7Smrj         NextGpeBlock = GpeXruptBlock->GpeBlockListHead;
112ae115bc7Smrj         while (NextGpeBlock->Next)
113ae115bc7Smrj         {
114ae115bc7Smrj             NextGpeBlock = NextGpeBlock->Next;
115ae115bc7Smrj         }
116ae115bc7Smrj 
117ae115bc7Smrj         NextGpeBlock->Next = GpeBlock;
118ae115bc7Smrj         GpeBlock->Previous = NextGpeBlock;
119ae115bc7Smrj     }
120ae115bc7Smrj     else
121ae115bc7Smrj     {
122ae115bc7Smrj         GpeXruptBlock->GpeBlockListHead = GpeBlock;
123ae115bc7Smrj     }
124ae115bc7Smrj 
125ae115bc7Smrj     GpeBlock->XruptBlock = GpeXruptBlock;
126ae115bc7Smrj     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
127ae115bc7Smrj 
128ae115bc7Smrj 
129ae115bc7Smrj UnlockAndExit:
130*385cc6b4SJerry Jelinek     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
131ae115bc7Smrj     return_ACPI_STATUS (Status);
132ae115bc7Smrj }
133ae115bc7Smrj 
134ae115bc7Smrj 
135ae115bc7Smrj /*******************************************************************************
136ae115bc7Smrj  *
137ae115bc7Smrj  * FUNCTION:    AcpiEvDeleteGpeBlock
138ae115bc7Smrj  *
139ae115bc7Smrj  * PARAMETERS:  GpeBlock            - Existing GPE block
140ae115bc7Smrj  *
141ae115bc7Smrj  * RETURN:      Status
142ae115bc7Smrj  *
143ae115bc7Smrj  * DESCRIPTION: Remove a GPE block
144ae115bc7Smrj  *
145ae115bc7Smrj  ******************************************************************************/
146ae115bc7Smrj 
147ae115bc7Smrj ACPI_STATUS
148ae115bc7Smrj AcpiEvDeleteGpeBlock (
149ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock)
150ae115bc7Smrj {
151ae115bc7Smrj     ACPI_STATUS             Status;
152ae115bc7Smrj     ACPI_CPU_FLAGS          Flags;
153ae115bc7Smrj 
154ae115bc7Smrj 
155ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvInstallGpeBlock);
156ae115bc7Smrj 
157ae115bc7Smrj 
158ae115bc7Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
159ae115bc7Smrj     if (ACPI_FAILURE (Status))
160ae115bc7Smrj     {
161ae115bc7Smrj         return_ACPI_STATUS (Status);
162ae115bc7Smrj     }
163ae115bc7Smrj 
164ae115bc7Smrj     /* Disable all GPEs in this block */
165ae115bc7Smrj 
166aa2aa9a6SDana Myers     Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL);
167ae115bc7Smrj 
168ae115bc7Smrj     if (!GpeBlock->Previous && !GpeBlock->Next)
169ae115bc7Smrj     {
170ae115bc7Smrj         /* This is the last GpeBlock on this interrupt */
171ae115bc7Smrj 
172ae115bc7Smrj         Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock);
173ae115bc7Smrj         if (ACPI_FAILURE (Status))
174ae115bc7Smrj         {
175ae115bc7Smrj             goto UnlockAndExit;
176ae115bc7Smrj         }
177ae115bc7Smrj     }
178ae115bc7Smrj     else
179ae115bc7Smrj     {
180ae115bc7Smrj         /* Remove the block on this interrupt with lock */
181ae115bc7Smrj 
182ae115bc7Smrj         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
183ae115bc7Smrj         if (GpeBlock->Previous)
184ae115bc7Smrj         {
185ae115bc7Smrj             GpeBlock->Previous->Next = GpeBlock->Next;
186ae115bc7Smrj         }
187ae115bc7Smrj         else
188ae115bc7Smrj         {
189ae115bc7Smrj             GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next;
190ae115bc7Smrj         }
191ae115bc7Smrj 
192ae115bc7Smrj         if (GpeBlock->Next)
193ae115bc7Smrj         {
194ae115bc7Smrj             GpeBlock->Next->Previous = GpeBlock->Previous;
195ae115bc7Smrj         }
196*385cc6b4SJerry Jelinek 
197ae115bc7Smrj         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
198ae115bc7Smrj     }
199ae115bc7Smrj 
20026f3cdf0SGordon Ross     AcpiCurrentGpeCount -= GpeBlock->GpeCount;
201aa2aa9a6SDana Myers 
202ae115bc7Smrj     /* Free the GpeBlock */
203ae115bc7Smrj 
204ae115bc7Smrj     ACPI_FREE (GpeBlock->RegisterInfo);
205ae115bc7Smrj     ACPI_FREE (GpeBlock->EventInfo);
206ae115bc7Smrj     ACPI_FREE (GpeBlock);
207ae115bc7Smrj 
208ae115bc7Smrj UnlockAndExit:
209ae115bc7Smrj     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
210ae115bc7Smrj     return_ACPI_STATUS (Status);
211ae115bc7Smrj }
212ae115bc7Smrj 
213ae115bc7Smrj 
214ae115bc7Smrj /*******************************************************************************
215ae115bc7Smrj  *
216ae115bc7Smrj  * FUNCTION:    AcpiEvCreateGpeInfoBlocks
217ae115bc7Smrj  *
218ae115bc7Smrj  * PARAMETERS:  GpeBlock    - New GPE block
219ae115bc7Smrj  *
220ae115bc7Smrj  * RETURN:      Status
221ae115bc7Smrj  *
222ae115bc7Smrj  * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block
223ae115bc7Smrj  *
224ae115bc7Smrj  ******************************************************************************/
225ae115bc7Smrj 
226ae115bc7Smrj static ACPI_STATUS
227ae115bc7Smrj AcpiEvCreateGpeInfoBlocks (
228ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock)
229ae115bc7Smrj {
230ae115bc7Smrj     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo = NULL;
231ae115bc7Smrj     ACPI_GPE_EVENT_INFO     *GpeEventInfo = NULL;
232ae115bc7Smrj     ACPI_GPE_EVENT_INFO     *ThisEvent;
233ae115bc7Smrj     ACPI_GPE_REGISTER_INFO  *ThisRegister;
234db2bae30SDana Myers     UINT32                  i;
235db2bae30SDana Myers     UINT32                  j;
236ae115bc7Smrj     ACPI_STATUS             Status;
237ae115bc7Smrj 
238ae115bc7Smrj 
239ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks);
240ae115bc7Smrj 
241ae115bc7Smrj 
242ae115bc7Smrj     /* Allocate the GPE register information block */
243ae115bc7Smrj 
244ae115bc7Smrj     GpeRegisterInfo = ACPI_ALLOCATE_ZEROED (
245ae115bc7Smrj         (ACPI_SIZE) GpeBlock->RegisterCount *
246ae115bc7Smrj         sizeof (ACPI_GPE_REGISTER_INFO));
247ae115bc7Smrj     if (!GpeRegisterInfo)
248ae115bc7Smrj     {
249ae115bc7Smrj         ACPI_ERROR ((AE_INFO,
250ae115bc7Smrj             "Could not allocate the GpeRegisterInfo table"));
251ae115bc7Smrj         return_ACPI_STATUS (AE_NO_MEMORY);
252ae115bc7Smrj     }
253ae115bc7Smrj 
254ae115bc7Smrj     /*
255ae115bc7Smrj      * Allocate the GPE EventInfo block. There are eight distinct GPEs
256ae115bc7Smrj      * per register. Initialization to zeros is sufficient.
257ae115bc7Smrj      */
25826f3cdf0SGordon Ross     GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount *
259ae115bc7Smrj         sizeof (ACPI_GPE_EVENT_INFO));
260ae115bc7Smrj     if (!GpeEventInfo)
261ae115bc7Smrj     {
262ae115bc7Smrj         ACPI_ERROR ((AE_INFO,
263ae115bc7Smrj             "Could not allocate the GpeEventInfo table"));
264ae115bc7Smrj         Status = AE_NO_MEMORY;
265ae115bc7Smrj         goto ErrorExit;
266ae115bc7Smrj     }
267ae115bc7Smrj 
268ae115bc7Smrj     /* Save the new Info arrays in the GPE block */
269ae115bc7Smrj 
270ae115bc7Smrj     GpeBlock->RegisterInfo = GpeRegisterInfo;
271ae115bc7Smrj     GpeBlock->EventInfo = GpeEventInfo;
272ae115bc7Smrj 
273ae115bc7Smrj     /*
274ae115bc7Smrj      * Initialize the GPE Register and Event structures. A goal of these
275aa2aa9a6SDana Myers      * tables is to hide the fact that there are two separate GPE register
276aa2aa9a6SDana Myers      * sets in a given GPE hardware block, the status registers occupy the
277aa2aa9a6SDana Myers      * first half, and the enable registers occupy the second half.
278ae115bc7Smrj      */
279ae115bc7Smrj     ThisRegister = GpeRegisterInfo;
280ae115bc7Smrj     ThisEvent = GpeEventInfo;
281ae115bc7Smrj 
282ae115bc7Smrj     for (i = 0; i < GpeBlock->RegisterCount; i++)
283ae115bc7Smrj     {
284ae115bc7Smrj         /* Init the RegisterInfo for this GPE register (8 GPEs) */
285ae115bc7Smrj 
286*385cc6b4SJerry Jelinek         ThisRegister->BaseGpeNumber = (UINT16)
287*385cc6b4SJerry Jelinek             (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH));
288ae115bc7Smrj 
289db2bae30SDana Myers         ThisRegister->StatusAddress.Address =
290*385cc6b4SJerry Jelinek             GpeBlock->Address + i;
291ae115bc7Smrj 
292db2bae30SDana Myers         ThisRegister->EnableAddress.Address =
293*385cc6b4SJerry Jelinek             GpeBlock->Address + i + GpeBlock->RegisterCount;
294ae115bc7Smrj 
295*385cc6b4SJerry Jelinek         ThisRegister->StatusAddress.SpaceId   = GpeBlock->SpaceId;
296*385cc6b4SJerry Jelinek         ThisRegister->EnableAddress.SpaceId   = GpeBlock->SpaceId;
297db2bae30SDana Myers         ThisRegister->StatusAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
298db2bae30SDana Myers         ThisRegister->EnableAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
299aa2aa9a6SDana Myers         ThisRegister->StatusAddress.BitOffset = 0;
300aa2aa9a6SDana Myers         ThisRegister->EnableAddress.BitOffset = 0;
301ae115bc7Smrj 
302ae115bc7Smrj         /* Init the EventInfo for each GPE within this register */
303ae115bc7Smrj 
304ae115bc7Smrj         for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
305ae115bc7Smrj         {
306db2bae30SDana Myers             ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j);
307ae115bc7Smrj             ThisEvent->RegisterInfo = ThisRegister;
308ae115bc7Smrj             ThisEvent++;
309ae115bc7Smrj         }
310ae115bc7Smrj 
311ae115bc7Smrj         /* Disable all GPEs within this register */
312ae115bc7Smrj 
31357190917SDana Myers         Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress);
314ae115bc7Smrj         if (ACPI_FAILURE (Status))
315ae115bc7Smrj         {
316ae115bc7Smrj             goto ErrorExit;
317ae115bc7Smrj         }
318ae115bc7Smrj 
319ae115bc7Smrj         /* Clear any pending GPE events within this register */
320ae115bc7Smrj 
32157190917SDana Myers         Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress);
322ae115bc7Smrj         if (ACPI_FAILURE (Status))
323ae115bc7Smrj         {
324ae115bc7Smrj             goto ErrorExit;
325ae115bc7Smrj         }
326ae115bc7Smrj 
327ae115bc7Smrj         ThisRegister++;
328ae115bc7Smrj     }
329ae115bc7Smrj 
330ae115bc7Smrj     return_ACPI_STATUS (AE_OK);
331ae115bc7Smrj 
332ae115bc7Smrj 
333ae115bc7Smrj ErrorExit:
334ae115bc7Smrj     if (GpeRegisterInfo)
335ae115bc7Smrj     {
336ae115bc7Smrj         ACPI_FREE (GpeRegisterInfo);
337ae115bc7Smrj     }
338ae115bc7Smrj     if (GpeEventInfo)
339ae115bc7Smrj     {
340ae115bc7Smrj         ACPI_FREE (GpeEventInfo);
341ae115bc7Smrj     }
342ae115bc7Smrj 
343ae115bc7Smrj     return_ACPI_STATUS (Status);
344ae115bc7Smrj }
345ae115bc7Smrj 
346ae115bc7Smrj 
347ae115bc7Smrj /*******************************************************************************
348ae115bc7Smrj  *
349ae115bc7Smrj  * FUNCTION:    AcpiEvCreateGpeBlock
350ae115bc7Smrj  *
351ae115bc7Smrj  * PARAMETERS:  GpeDevice           - Handle to the parent GPE block
352ae115bc7Smrj  *              GpeBlockAddress     - Address and SpaceID
353ae115bc7Smrj  *              RegisterCount       - Number of GPE register pairs in the block
354ae115bc7Smrj  *              GpeBlockBaseNumber  - Starting GPE number for the block
355ae115bc7Smrj  *              InterruptNumber     - H/W interrupt for the block
356ae115bc7Smrj  *              ReturnGpeBlock      - Where the new block descriptor is returned
357ae115bc7Smrj  *
358ae115bc7Smrj  * RETURN:      Status
359ae115bc7Smrj  *
360ae115bc7Smrj  * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
361ae115bc7Smrj  *              the block are disabled at exit.
362ae115bc7Smrj  *              Note: Assumes namespace is locked.
363ae115bc7Smrj  *
364ae115bc7Smrj  ******************************************************************************/
365ae115bc7Smrj 
366ae115bc7Smrj ACPI_STATUS
367ae115bc7Smrj AcpiEvCreateGpeBlock (
368ae115bc7Smrj     ACPI_NAMESPACE_NODE     *GpeDevice,
369*385cc6b4SJerry Jelinek     UINT64                  Address,
370*385cc6b4SJerry Jelinek     UINT8                   SpaceId,
371ae115bc7Smrj     UINT32                  RegisterCount,
372*385cc6b4SJerry Jelinek     UINT16                  GpeBlockBaseNumber,
373ae115bc7Smrj     UINT32                  InterruptNumber,
374ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     **ReturnGpeBlock)
375ae115bc7Smrj {
376ae115bc7Smrj     ACPI_STATUS             Status;
377ae115bc7Smrj     ACPI_GPE_BLOCK_INFO     *GpeBlock;
37826f3cdf0SGordon Ross     ACPI_GPE_WALK_INFO      WalkInfo;
379ae115bc7Smrj 
380ae115bc7Smrj 
381ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvCreateGpeBlock);
382ae115bc7Smrj 
383ae115bc7Smrj 
384ae115bc7Smrj     if (!RegisterCount)
385ae115bc7Smrj     {
386ae115bc7Smrj         return_ACPI_STATUS (AE_OK);
387ae115bc7Smrj     }
388ae115bc7Smrj 
389ae115bc7Smrj     /* Allocate a new GPE block */
390ae115bc7Smrj 
391ae115bc7Smrj     GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO));
392ae115bc7Smrj     if (!GpeBlock)
393ae115bc7Smrj     {
394ae115bc7Smrj         return_ACPI_STATUS (AE_NO_MEMORY);
395ae115bc7Smrj     }
396ae115bc7Smrj 
397ae115bc7Smrj     /* Initialize the new GPE block */
398ae115bc7Smrj 
399*385cc6b4SJerry Jelinek     GpeBlock->Address = Address;
400*385cc6b4SJerry Jelinek     GpeBlock->SpaceId = SpaceId;
401ae115bc7Smrj     GpeBlock->Node = GpeDevice;
40226f3cdf0SGordon Ross     GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH);
40326f3cdf0SGordon Ross     GpeBlock->Initialized = FALSE;
404ae115bc7Smrj     GpeBlock->RegisterCount = RegisterCount;
405ae115bc7Smrj     GpeBlock->BlockBaseNumber = GpeBlockBaseNumber;
406ae115bc7Smrj 
407ae115bc7Smrj     /*
408ae115bc7Smrj      * Create the RegisterInfo and EventInfo sub-structures
409ae115bc7Smrj      * Note: disables and clears all GPEs in the block
410ae115bc7Smrj      */
411ae115bc7Smrj     Status = AcpiEvCreateGpeInfoBlocks (GpeBlock);
412ae115bc7Smrj     if (ACPI_FAILURE (Status))
413ae115bc7Smrj     {
414ae115bc7Smrj         ACPI_FREE (GpeBlock);
415ae115bc7Smrj         return_ACPI_STATUS (Status);
416ae115bc7Smrj     }
417ae115bc7Smrj 
418ae115bc7Smrj     /* Install the new block in the global lists */
419ae115bc7Smrj 
420ae115bc7Smrj     Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber);
421ae115bc7Smrj     if (ACPI_FAILURE (Status))
422ae115bc7Smrj     {
423*385cc6b4SJerry Jelinek         ACPI_FREE (GpeBlock->RegisterInfo);
424*385cc6b4SJerry Jelinek         ACPI_FREE (GpeBlock->EventInfo);
425ae115bc7Smrj         ACPI_FREE (GpeBlock);
426ae115bc7Smrj         return_ACPI_STATUS (Status);
427ae115bc7Smrj     }
428ae115bc7Smrj 
42926f3cdf0SGordon Ross     AcpiGbl_AllGpesInitialized = FALSE;
43026f3cdf0SGordon Ross 
43126f3cdf0SGordon Ross     /* Find all GPE methods (_Lxx or_Exx) for this block */
43226f3cdf0SGordon Ross 
43326f3cdf0SGordon Ross     WalkInfo.GpeBlock = GpeBlock;
43426f3cdf0SGordon Ross     WalkInfo.GpeDevice = GpeDevice;
43526f3cdf0SGordon Ross     WalkInfo.ExecuteByOwnerId = FALSE;
436ae115bc7Smrj 
437ae115bc7Smrj     Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
438ae115bc7Smrj         ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
43926f3cdf0SGordon Ross         AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL);
440ae115bc7Smrj 
441ae115bc7Smrj     /* Return the new block */
442ae115bc7Smrj 
443ae115bc7Smrj     if (ReturnGpeBlock)
444ae115bc7Smrj     {
445ae115bc7Smrj         (*ReturnGpeBlock) = GpeBlock;
446ae115bc7Smrj     }
447ae115bc7Smrj 
448*385cc6b4SJerry Jelinek     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
449*385cc6b4SJerry Jelinek         "    Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
450ae115bc7Smrj         (UINT32) GpeBlock->BlockBaseNumber,
45126f3cdf0SGordon Ross         (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)),
452*385cc6b4SJerry Jelinek         GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber,
453*385cc6b4SJerry Jelinek         InterruptNumber == AcpiGbl_FADT.SciInterrupt ? " (SCI)" : ""));
454ae115bc7Smrj 
455aa2aa9a6SDana Myers     /* Update global count of currently available GPEs */
456aa2aa9a6SDana Myers 
45726f3cdf0SGordon Ross     AcpiCurrentGpeCount += GpeBlock->GpeCount;
458ae115bc7Smrj     return_ACPI_STATUS (AE_OK);
459ae115bc7Smrj }
460ae115bc7Smrj 
461ae115bc7Smrj 
462ae115bc7Smrj /*******************************************************************************
463ae115bc7Smrj  *
464ae115bc7Smrj  * FUNCTION:    AcpiEvInitializeGpeBlock
465ae115bc7Smrj  *
46626f3cdf0SGordon Ross  * PARAMETERS:  ACPI_GPE_CALLBACK
467ae115bc7Smrj  *
468ae115bc7Smrj  * RETURN:      Status
469ae115bc7Smrj  *
47026f3cdf0SGordon Ross  * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
47126f3cdf0SGordon Ross  *              associated methods.
472ae115bc7Smrj  *              Note: Assumes namespace is locked.
473ae115bc7Smrj  *
474ae115bc7Smrj  ******************************************************************************/
475ae115bc7Smrj 
476ae115bc7Smrj ACPI_STATUS
477ae115bc7Smrj AcpiEvInitializeGpeBlock (
47826f3cdf0SGordon Ross     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
47926f3cdf0SGordon Ross     ACPI_GPE_BLOCK_INFO     *GpeBlock,
48026f3cdf0SGordon Ross     void                    *Ignored)
481ae115bc7Smrj {
482ae115bc7Smrj     ACPI_STATUS             Status;
483ae115bc7Smrj     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
484ae115bc7Smrj     UINT32                  GpeEnabledCount;
48526f3cdf0SGordon Ross     UINT32                  GpeIndex;
486db2bae30SDana Myers     UINT32                  i;
487db2bae30SDana Myers     UINT32                  j;
488ae115bc7Smrj 
489ae115bc7Smrj 
490ae115bc7Smrj     ACPI_FUNCTION_TRACE (EvInitializeGpeBlock);
491ae115bc7Smrj 
492ae115bc7Smrj 
49326f3cdf0SGordon Ross     /*
49426f3cdf0SGordon Ross      * Ignore a null GPE block (e.g., if no GPE block 1 exists), and
49526f3cdf0SGordon Ross      * any GPE blocks that have been initialized already.
49626f3cdf0SGordon Ross      */
49726f3cdf0SGordon Ross     if (!GpeBlock || GpeBlock->Initialized)
498ae115bc7Smrj     {
499ae115bc7Smrj         return_ACPI_STATUS (AE_OK);
500ae115bc7Smrj     }
501ae115bc7Smrj 
502ae115bc7Smrj     /*
50326f3cdf0SGordon Ross      * Enable all GPEs that have a corresponding method and have the
50426f3cdf0SGordon Ross      * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
50526f3cdf0SGordon Ross      * must be enabled via the acpi_enable_gpe() interface.
506ae115bc7Smrj      */
507ae115bc7Smrj     GpeEnabledCount = 0;
508ae115bc7Smrj 
509ae115bc7Smrj     for (i = 0; i < GpeBlock->RegisterCount; i++)
510ae115bc7Smrj     {
51126f3cdf0SGordon Ross         for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
512ae115bc7Smrj         {
513ae115bc7Smrj             /* Get the info block for this particular GPE */
514ae115bc7Smrj 
51526f3cdf0SGordon Ross             GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j;
51626f3cdf0SGordon Ross             GpeEventInfo = &GpeBlock->EventInfo[GpeIndex];
517ae115bc7Smrj 
51826f3cdf0SGordon Ross             /*
51926f3cdf0SGordon Ross              * Ignore GPEs that have no corresponding _Lxx/_Exx method
52026f3cdf0SGordon Ross              * and GPEs that are used to wake the system
52126f3cdf0SGordon Ross              */
522*385cc6b4SJerry Jelinek             if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_NONE) ||
523*385cc6b4SJerry Jelinek                 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_HANDLER) ||
524*385cc6b4SJerry Jelinek                 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_RAW_HANDLER) ||
52526f3cdf0SGordon Ross                 (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
526ae115bc7Smrj             {
52726f3cdf0SGordon Ross                 continue;
52826f3cdf0SGordon Ross             }
52926f3cdf0SGordon Ross 
53026f3cdf0SGordon Ross             Status = AcpiEvAddGpeReference (GpeEventInfo);
53126f3cdf0SGordon Ross             if (ACPI_FAILURE (Status))
53226f3cdf0SGordon Ross             {
53326f3cdf0SGordon Ross                 ACPI_EXCEPTION ((AE_INFO, Status,
53426f3cdf0SGordon Ross                     "Could not enable GPE 0x%02X",
53526f3cdf0SGordon Ross                     GpeIndex + GpeBlock->BlockBaseNumber));
53626f3cdf0SGordon Ross                 continue;
53726f3cdf0SGordon Ross             }
53826f3cdf0SGordon Ross 
539ae115bc7Smrj             GpeEnabledCount++;
540ae115bc7Smrj         }
54126f3cdf0SGordon Ross     }
542ae115bc7Smrj 
54326f3cdf0SGordon Ross     if (GpeEnabledCount)
544ae115bc7Smrj     {
545*385cc6b4SJerry Jelinek         ACPI_INFO ((
546*385cc6b4SJerry Jelinek             "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount,
547*385cc6b4SJerry Jelinek             (UINT32) GpeBlock->BlockBaseNumber,
548*385cc6b4SJerry Jelinek             (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1))));
549ae115bc7Smrj     }
550ae115bc7Smrj 
55126f3cdf0SGordon Ross     GpeBlock->Initialized = TRUE;
552ae115bc7Smrj     return_ACPI_STATUS (AE_OK);
553ae115bc7Smrj }
554ae115bc7Smrj 
555*385cc6b4SJerry Jelinek #endif /* !ACPI_REDUCED_HARDWARE */
556