| 1 | |
| 2 | |
| 3 | *
|
| 4 | * Module Name: evsci - System Control Interrupt configuration and
|
| 5 | * legacy to ACPI mode state transition functions
|
| 6 | *
|
| 7 | *****************************************************************************
|
| 8 |
|
| 9 | #include <acpi/acpi.h>
|
| 10 | #include "accommon.h"
|
| 11 | #include "acevents.h"
|
| 12 |
|
| 13 | #define _COMPONENT ACPI_EVENTS
|
| 14 | ACPI_MODULE_NAME("evsci")
|
| 15 | #if (!ACPI_REDUCED_HARDWARE)
|
| 16 |
|
| 17 | static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
|
| 18 |
|
| 19 | |
| 20 | *
|
| 21 | * FUNCTION: acpi_ev_sci_dispatch
|
| 22 | *
|
| 23 | * PARAMETERS: None
|
| 24 | *
|
| 25 | * RETURN: Status code indicates whether interrupt was handled.
|
| 26 | *
|
| 27 | * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
|
| 28 | *
|
| 29 | *****************************************************************************
|
| 30 |
|
| 31 | u32 acpi_ev_sci_dispatch(void)
|
| 32 | {
|
| 33 | struct acpi_sci_handler_info *sci_handler;
|
| 34 | acpi_cpu_flags flags;
|
| 35 | u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
|
| 36 |
|
| 37 | ACPI_FUNCTION_NAME(ev_sci_dispatch);
|
| 38 |
|
| 39 |
|
| 40 |
|
| 41 | if (!acpi_gbl_sci_handler_list) {
|
| 42 | return (int_status);
|
| 43 | }
|
| 44 |
|
| 45 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
| 46 |
|
| 47 |
|
| 48 |
|
| 49 | sci_handler = acpi_gbl_sci_handler_list;
|
| 50 | while (sci_handler) {
|
| 51 |
|
| 52 |
|
| 53 |
|
| 54 | int_status |= sci_handler->address(sci_handler->context);
|
| 55 |
|
| 56 | sci_handler = sci_handler->next;
|
| 57 | }
|
| 58 |
|
| 59 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
| 60 | return (int_status);
|
| 61 | }
|
| 62 |
|
| 63 | |
| 64 | *
|
| 65 | * FUNCTION: acpi_ev_sci_xrupt_handler
|
| 66 | *
|
| 67 | * PARAMETERS: context - Calling Context
|
| 68 | *
|
| 69 | * RETURN: Status code indicates whether interrupt was handled.
|
| 70 | *
|
| 71 | * DESCRIPTION: Interrupt handler that will figure out what function or
|
| 72 | * control method to call to deal with a SCI.
|
| 73 | *
|
| 74 | *****************************************************************************
|
| 75 |
|
| 76 | static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
|
| 77 | {
|
| 78 | struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
|
| 79 | u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
|
| 80 |
|
| 81 | ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
|
| 82 |
|
| 83 | |
| 84 | * We are guaranteed by the ACPICA initialization/shutdown code that
|
| 85 | * if this interrupt handler is installed, ACPI is enabled.
|
| 86 |
|
| 87 |
|
| 88 | |
| 89 | * Fixed Events:
|
| 90 | * Check for and dispatch any Fixed Events that have occurred
|
| 91 |
|
| 92 | interrupt_handled |= acpi_ev_fixed_event_detect();
|
| 93 |
|
| 94 | |
| 95 | * General Purpose Events:
|
| 96 | * Check for and dispatch any GPEs that have occurred
|
| 97 |
|
| 98 | interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
|
| 99 |
|
| 100 |
|
| 101 |
|
| 102 | interrupt_handled |= acpi_ev_sci_dispatch();
|
| 103 |
|
| 104 | acpi_sci_count++;
|
| 105 | return_UINT32(interrupt_handled);
|
| 106 | }
|
| 107 |
|
| 108 | |
| 109 | *
|
| 110 | * FUNCTION: acpi_ev_gpe_xrupt_handler
|
| 111 | *
|
| 112 | * PARAMETERS: context - Calling Context
|
| 113 | *
|
| 114 | * RETURN: Status code indicates whether interrupt was handled.
|
| 115 | *
|
| 116 | * DESCRIPTION: Handler for GPE Block Device interrupts
|
| 117 | *
|
| 118 | *****************************************************************************
|
| 119 |
|
| 120 | u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
|
| 121 | {
|
| 122 | struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
|
| 123 | u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
|
| 124 |
|
| 125 | ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
|
| 126 |
|
| 127 | |
| 128 | * We are guaranteed by the ACPICA initialization/shutdown code that
|
| 129 | * if this interrupt handler is installed, ACPI is enabled.
|
| 130 |
|
| 131 |
|
| 132 |
|
| 133 |
|
| 134 | interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
|
| 135 | return_UINT32(interrupt_handled);
|
| 136 | }
|
| 137 |
|
| 138 | |
| 139 | *
|
| 140 | * FUNCTION: acpi_ev_install_sci_handler
|
| 141 | *
|
| 142 | * PARAMETERS: none
|
| 143 | *
|
| 144 | * RETURN: Status
|
| 145 | *
|
| 146 | * DESCRIPTION: Installs SCI handler.
|
| 147 | *
|
| 148 | *****************************************************************************
|
| 149 |
|
| 150 | u32 acpi_ev_install_sci_handler(void)
|
| 151 | {
|
| 152 | u32 status = AE_OK;
|
| 153 |
|
| 154 | ACPI_FUNCTION_TRACE(ev_install_sci_handler);
|
| 155 |
|
| 156 | status =
|
| 157 | acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
|
| 158 | acpi_ev_sci_xrupt_handler,
|
| 159 | acpi_gbl_gpe_xrupt_list_head);
|
| 160 | return_ACPI_STATUS(status);
|
| 161 | }
|
| 162 |
|
| 163 | |
| 164 | *
|
| 165 | * FUNCTION: acpi_ev_remove_all_sci_handlers
|
| 166 | *
|
| 167 | * PARAMETERS: none
|
| 168 | *
|
| 169 | * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not
|
| 170 | * installed to begin with
|
| 171 | *
|
| 172 | * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
|
| 173 | * taken. Remove all host-installed SCI handlers.
|
| 174 | *
|
| 175 | * Note: It doesn't seem important to disable all events or set the event
|
| 176 | * enable registers to their original values. The OS should disable
|
| 177 | * the SCI interrupt level when the handler is removed, so no more
|
| 178 | * events will come in.
|
| 179 | *
|
| 180 | *****************************************************************************
|
| 181 |
|
| 182 | acpi_status acpi_ev_remove_all_sci_handlers(void)
|
| 183 | {
|
| 184 | struct acpi_sci_handler_info *sci_handler;
|
| 185 | acpi_cpu_flags flags;
|
| 186 | acpi_status status;
|
| 187 |
|
| 188 | ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
|
| 189 |
|
| 190 |
|
| 191 |
|
| 192 | status =
|
| 193 | acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
|
| 194 | acpi_ev_sci_xrupt_handler);
|
| 195 |
|
| 196 | if (!acpi_gbl_sci_handler_list) {
|
| 197 | return (status);
|
| 198 | }
|
| 199 |
|
| 200 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
|
| 201 |
|
| 202 |
|
| 203 |
|
| 204 | while (acpi_gbl_sci_handler_list) {
|
| 205 | sci_handler = acpi_gbl_sci_handler_list;
|
| 206 | acpi_gbl_sci_handler_list = sci_handler->next;
|
| 207 | ACPI_FREE(sci_handler);
|
| 208 | }
|
| 209 |
|
| 210 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
| 211 | return_ACPI_STATUS(status);
|
| 212 | }
|
| 213 |
|
| 214 | #endif
|