1 /****************************************************************************** 2 * 3 * Module Name: evevent - Fixed Event handling and dispatch 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 52 53 /* Local prototypes */ 54 55 static ACPI_STATUS 56 AcpiEvFixedEventInitialize ( 57 void); 58 59 static UINT32 60 AcpiEvFixedEventDispatch ( 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 76 ACPI_STATUS 77 AcpiEvInitializeEvents ( 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 130 ACPI_STATUS 131 AcpiEvInstallXruptHandlers ( 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 184 static ACPI_STATUS 185 AcpiEvFixedEventInitialize ( 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 * disable all of 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 (i == ACPI_EVENT_PCIE_WAKE) ? 208 ACPI_ENABLE_EVENT : ACPI_DISABLE_EVENT); 209 if (ACPI_FAILURE (Status)) 210 { 211 return (Status); 212 } 213 } 214 } 215 216 return (AE_OK); 217 } 218 219 220 /******************************************************************************* 221 * 222 * FUNCTION: AcpiEvFixedEventDetect 223 * 224 * PARAMETERS: None 225 * 226 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 227 * 228 * DESCRIPTION: Checks the PM status register for active fixed events 229 * 230 ******************************************************************************/ 231 232 UINT32 233 AcpiEvFixedEventDetect ( 234 void) 235 { 236 UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 237 UINT32 FixedStatus; 238 UINT32 FixedEnable; 239 UINT32 i; 240 ACPI_STATUS Status; 241 242 243 ACPI_FUNCTION_NAME (EvFixedEventDetect); 244 245 246 /* 247 * Read the fixed feature status and enable registers, as all the cases 248 * depend on their values. Ignore errors here. 249 */ 250 Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, &FixedStatus); 251 Status |= AcpiHwRegisterRead (ACPI_REGISTER_PM1_ENABLE, &FixedEnable); 252 if (ACPI_FAILURE (Status)) 253 { 254 return (IntStatus); 255 } 256 257 if (FixedEnable & ACPI_BITMASK_PCIEXP_WAKE_DISABLE) 258 FixedEnable &= ~ACPI_BITMASK_PCIEXP_WAKE_DISABLE; 259 else 260 FixedEnable |= ACPI_BITMASK_PCIEXP_WAKE_DISABLE; 261 262 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 263 "Fixed Event Block: Enable %08X Status %08X\n", 264 FixedEnable, FixedStatus)); 265 266 /* 267 * Check for all possible Fixed Events and dispatch those that are active 268 */ 269 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) 270 { 271 /* Both the status and enable bits must be on for this event */ 272 273 if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) && 274 (FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask)) 275 { 276 /* 277 * Found an active (signalled) event. Invoke global event 278 * handler if present. 279 */ 280 AcpiFixedEventCount[i]++; 281 if (AcpiGbl_GlobalEventHandler) 282 { 283 AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_FIXED, NULL, 284 i, AcpiGbl_GlobalEventHandlerContext); 285 } 286 287 IntStatus |= AcpiEvFixedEventDispatch (i); 288 } 289 } 290 291 return (IntStatus); 292 } 293 294 295 /******************************************************************************* 296 * 297 * FUNCTION: AcpiEvFixedEventDispatch 298 * 299 * PARAMETERS: Event - Event type 300 * 301 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 302 * 303 * DESCRIPTION: Clears the status bit for the requested event, calls the 304 * handler that previously registered for the event. 305 * NOTE: If there is no handler for the event, the event is 306 * disabled to prevent further interrupts. 307 * 308 ******************************************************************************/ 309 310 static UINT32 311 AcpiEvFixedEventDispatch ( 312 UINT32 Event) 313 { 314 315 ACPI_FUNCTION_ENTRY (); 316 317 318 /* Clear the status bit */ 319 320 (void) AcpiWriteBitRegister ( 321 AcpiGbl_FixedEventInfo[Event].StatusRegisterId, 322 ACPI_CLEAR_STATUS); 323 324 /* 325 * Make sure that a handler exists. If not, report an error 326 * and disable the event to prevent further interrupts. 327 */ 328 if (!AcpiGbl_FixedEventHandlers[Event].Handler) 329 { 330 (void) AcpiWriteBitRegister ( 331 AcpiGbl_FixedEventInfo[Event].EnableRegisterId, 332 (Event == ACPI_EVENT_PCIE_WAKE) ? 333 ACPI_ENABLE_EVENT : ACPI_DISABLE_EVENT); 334 335 ACPI_ERROR ((AE_INFO, 336 "No installed handler for fixed event - %s (%u), disabling", 337 AcpiUtGetEventName (Event), Event)); 338 339 return (ACPI_INTERRUPT_NOT_HANDLED); 340 } 341 342 /* Invoke the Fixed Event handler */ 343 344 return ((AcpiGbl_FixedEventHandlers[Event].Handler)( 345 AcpiGbl_FixedEventHandlers[Event].Context)); 346 } 347 348 #endif /* !ACPI_REDUCED_HARDWARE */ 349