evevent.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: evevent - Fixed Event handling and dispatch
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acevents.h>
47
48#define _COMPONENT          ACPI_EVENTS
49        ACPI_MODULE_NAME    ("evevent")
50
51#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
52
53/* Local prototypes */
54
55static ACPI_STATUS
56AcpiEvFixedEventInitialize (
57    void);
58
59static UINT32
60AcpiEvFixedEventDispatch (
61    UINT32                  Event);
62
63
64/*******************************************************************************
65 *
66 * FUNCTION:    AcpiEvInitializeEvents
67 *
68 * PARAMETERS:  None
69 *
70 * RETURN:      Status
71 *
72 * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
73 *
74 ******************************************************************************/
75
76ACPI_STATUS
77AcpiEvInitializeEvents (
78    void)
79{
80    ACPI_STATUS             Status;
81
82
83    ACPI_FUNCTION_TRACE (EvInitializeEvents);
84
85
86    /* If Hardware Reduced flag is set, there are no fixed events */
87
88    if (AcpiGbl_ReducedHardware)
89    {
90        return_ACPI_STATUS (AE_OK);
91    }
92
93    /*
94     * Initialize the Fixed and General Purpose Events. This is done prior to
95     * enabling SCIs to prevent interrupts from occurring before the handlers
96     * are installed.
97     */
98    Status = AcpiEvFixedEventInitialize ();
99    if (ACPI_FAILURE (Status))
100    {
101        ACPI_EXCEPTION ((AE_INFO, Status,
102            "Unable to initialize fixed events"));
103        return_ACPI_STATUS (Status);
104    }
105
106    Status = AcpiEvGpeInitialize ();
107    if (ACPI_FAILURE (Status))
108    {
109        ACPI_EXCEPTION ((AE_INFO, Status,
110            "Unable to initialize general purpose events"));
111        return_ACPI_STATUS (Status);
112    }
113
114    return_ACPI_STATUS (Status);
115}
116
117
118/*******************************************************************************
119 *
120 * FUNCTION:    AcpiEvInstallXruptHandlers
121 *
122 * PARAMETERS:  None
123 *
124 * RETURN:      Status
125 *
126 * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
127 *
128 ******************************************************************************/
129
130ACPI_STATUS
131AcpiEvInstallXruptHandlers (
132    void)
133{
134    ACPI_STATUS             Status;
135
136
137    ACPI_FUNCTION_TRACE (EvInstallXruptHandlers);
138
139
140    /* If Hardware Reduced flag is set, there is no ACPI h/w */
141
142    if (AcpiGbl_ReducedHardware)
143    {
144        return_ACPI_STATUS (AE_OK);
145    }
146
147    /* Install the SCI handler */
148
149    Status = AcpiEvInstallSciHandler ();
150    if (ACPI_FAILURE (Status))
151    {
152        ACPI_EXCEPTION ((AE_INFO, Status,
153            "Unable to install System Control Interrupt handler"));
154        return_ACPI_STATUS (Status);
155    }
156
157    /* Install the handler for the Global Lock */
158
159    Status = AcpiEvInitGlobalLockHandler ();
160    if (ACPI_FAILURE (Status))
161    {
162        ACPI_EXCEPTION ((AE_INFO, Status,
163            "Unable to initialize Global Lock handler"));
164        return_ACPI_STATUS (Status);
165    }
166
167    AcpiGbl_EventsInitialized = TRUE;
168    return_ACPI_STATUS (Status);
169}
170
171
172/*******************************************************************************
173 *
174 * FUNCTION:    AcpiEvFixedEventInitialize
175 *
176 * PARAMETERS:  None
177 *
178 * RETURN:      Status
179 *
180 * DESCRIPTION: Install the fixed event handlers and disable all fixed events.
181 *
182 ******************************************************************************/
183
184static ACPI_STATUS
185AcpiEvFixedEventInitialize (
186    void)
187{
188    UINT32                  i;
189    ACPI_STATUS             Status;
190
191
192    /*
193     * Initialize the structure that keeps track of fixed event handlers and
194     * enable the fixed events.
195     */
196    for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
197    {
198        AcpiGbl_FixedEventHandlers[i].Handler = NULL;
199        AcpiGbl_FixedEventHandlers[i].Context = NULL;
200
201        /* Disable the fixed event */
202
203        if (AcpiGbl_FixedEventInfo[i].EnableRegisterId != 0xFF)
204        {
205            Status = AcpiWriteBitRegister (
206                        AcpiGbl_FixedEventInfo[i].EnableRegisterId,
207                        ACPI_DISABLE_EVENT);
208            if (ACPI_FAILURE (Status))
209            {
210                return (Status);
211            }
212        }
213    }
214
215    return (AE_OK);
216}
217
218
219/*******************************************************************************
220 *
221 * FUNCTION:    AcpiEvFixedEventDetect
222 *
223 * PARAMETERS:  None
224 *
225 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
226 *
227 * DESCRIPTION: Checks the PM status register for active fixed events
228 *
229 ******************************************************************************/
230
231UINT32
232AcpiEvFixedEventDetect (
233    void)
234{
235    UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
236    UINT32                  FixedStatus;
237    UINT32                  FixedEnable;
238    UINT32                  i;
239
240
241    ACPI_FUNCTION_NAME (EvFixedEventDetect);
242
243
244    /*
245     * Read the fixed feature status and enable registers, as all the cases
246     * depend on their values. Ignore errors here.
247     */
248    (void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, &FixedStatus);
249    (void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_ENABLE, &FixedEnable);
250
251    ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
252        "Fixed Event Block: Enable %08X Status %08X\n",
253        FixedEnable, FixedStatus));
254
255    /*
256     * Check for all possible Fixed Events and dispatch those that are active
257     */
258    for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
259    {
260        /* Both the status and enable bits must be on for this event */
261
262        if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) &&
263            (FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask))
264        {
265            /*
266             * Found an active (signalled) event. Invoke global event
267             * handler if present.
268             */
269            AcpiFixedEventCount[i]++;
270            if (AcpiGbl_GlobalEventHandler)
271            {
272                AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_FIXED, NULL,
273                     i, AcpiGbl_GlobalEventHandlerContext);
274            }
275
276            IntStatus |= AcpiEvFixedEventDispatch (i);
277        }
278    }
279
280    return (IntStatus);
281}
282
283
284/*******************************************************************************
285 *
286 * FUNCTION:    AcpiEvFixedEventDispatch
287 *
288 * PARAMETERS:  Event               - Event type
289 *
290 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
291 *
292 * DESCRIPTION: Clears the status bit for the requested event, calls the
293 *              handler that previously registered for the event.
294 *              NOTE: If there is no handler for the event, the event is
295 *              disabled to prevent further interrupts.
296 *
297 ******************************************************************************/
298
299static UINT32
300AcpiEvFixedEventDispatch (
301    UINT32                  Event)
302{
303
304    ACPI_FUNCTION_ENTRY ();
305
306
307    /* Clear the status bit */
308
309    (void) AcpiWriteBitRegister (
310            AcpiGbl_FixedEventInfo[Event].StatusRegisterId,
311            ACPI_CLEAR_STATUS);
312
313    /*
314     * Make sure that a handler exists. If not, report an error
315     * and disable the event to prevent further interrupts.
316     */
317    if (!AcpiGbl_FixedEventHandlers[Event].Handler)
318    {
319        (void) AcpiWriteBitRegister (
320                AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
321                ACPI_DISABLE_EVENT);
322
323        ACPI_ERROR ((AE_INFO,
324            "No installed handler for fixed event - %s (%u), disabling",
325            AcpiUtGetEventName (Event), Event));
326
327        return (ACPI_INTERRUPT_NOT_HANDLED);
328    }
329
330    /* Invoke the Fixed Event handler */
331
332    return ((AcpiGbl_FixedEventHandlers[Event].Handler)(
333                AcpiGbl_FixedEventHandlers[Event].Context));
334}
335
336#endif /* !ACPI_REDUCED_HARDWARE */
337