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