📄 evevent.c
字号:
} /* GPE Block 1 */ for (i = 0; i < gpe1_register_count; i++) { acpi_gbl_gpe_registers[register_index].status_addr = (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i); acpi_gbl_gpe_registers[register_index].enable_addr = (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i + gpe1_register_count); acpi_gbl_gpe_registers[register_index].gpe_base = (u8) (acpi_gbl_FADT->gpe1_base + MUL_8 (i)); for (j = 0; j < 8; j++) { gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; } /* * Clear the status/enable registers. Note that status registers * are cleared by writing a '1', while enable registers are cleared * by writing a '0'. */ acpi_os_write_port (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00, 8); acpi_os_write_port (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF, 8); register_index++; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE registers: %X@%8.8X%8.8X (Blk0) %X@%8.8X%8.8X (Blk1)\n", gpe0register_count, HIDWORD(acpi_gbl_FADT->Xgpe0blk.address), LODWORD(acpi_gbl_FADT->Xgpe0blk.address), gpe1_register_count, HIDWORD(acpi_gbl_FADT->Xgpe1_blk.address), LODWORD(acpi_gbl_FADT->Xgpe1_blk.address))); return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION: Acpi_ev_save_method_info * * PARAMETERS: None * * RETURN: None * * DESCRIPTION: Called from Acpi_walk_namespace. Expects each object to be a * control method under the _GPE portion of the namespace. * Extract the name and GPE type from the object, saving this * information for quick lookup during GPE dispatch * * The name of each GPE control method is of the form: * "_Lnn" or "_Enn" * Where: * L - means that the GPE is level triggered * E - means that the GPE is edge triggered * nn - is the GPE number * ******************************************************************************/static acpi_statusacpi_ev_save_method_info ( acpi_handle obj_handle, u32 level, void *obj_desc, void **return_value){ u32 gpe_number; NATIVE_CHAR name[ACPI_NAME_SIZE + 1]; u8 type; PROC_NAME ("Ev_save_method_info"); /* Extract the name from the object and convert to a string */ MOVE_UNALIGNED32_TO_32 (name, &((acpi_namespace_node *) obj_handle)->name); name[ACPI_NAME_SIZE] = 0; /* * Edge/Level determination is based on the 2nd s8 of the method name */ if (name[1] == 'L') { type = ACPI_EVENT_LEVEL_TRIGGERED; } else if (name[1] == 'E') { type = ACPI_EVENT_EDGE_TRIGGERED; } else { /* Unknown method type, just ignore it! */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n", name)); return (AE_OK); } /* Convert the last two characters of the name to the Gpe Number */ gpe_number = STRTOUL (&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n", name)); return (AE_OK); } /* Ensure that we have a valid GPE number */ if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { /* Not valid, all we can do here is ignore it */ return (AE_OK); } /* * Now we can add this information to the Gpe_info block * for use during dispatch of this GPE. */ acpi_gbl_gpe_info [gpe_number].type = type; acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle; /* * Enable the GPE (SCIs should be disabled at this point) */ acpi_hw_enable_gpe (gpe_number); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n", name, gpe_number)); return (AE_OK);}/******************************************************************************* * * FUNCTION: Acpi_ev_init_gpe_control_methods * * PARAMETERS: None * * RETURN: None * * DESCRIPTION: Obtain the control methods associated with the GPEs. * * NOTE: Must be called AFTER namespace initialization! * ******************************************************************************/acpi_statusacpi_ev_init_gpe_control_methods (void){ acpi_status status; FUNCTION_TRACE ("Ev_init_gpe_control_methods"); /* Get a permanent handle to the _GPE object */ status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Traverse the namespace under \_GPE to find all methods there */ status = acpi_walk_namespace (ACPI_TYPE_METHOD, acpi_gbl_gpe_obj_handle, ACPI_UINT32_MAX, acpi_ev_save_method_info, NULL, NULL); return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: Acpi_ev_gpe_detect * * PARAMETERS: None * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Detect if any GP events have occurred * ******************************************************************************/u32acpi_ev_gpe_detect (void){ u32 int_status = INTERRUPT_NOT_HANDLED; u32 i; u32 j; u8 enabled_status_byte; u8 bit_mask; PROC_NAME ("Ev_gpe_detect"); /* * Read all of the 8-bit GPE status and enable registers * in both of the register blocks, saving all of it. * Find all currently active GP events. */ for (i = 0; i < acpi_gbl_gpe_register_count; i++) { acpi_os_read_port (acpi_gbl_gpe_registers[i].status_addr, &acpi_gbl_gpe_registers[i].status, 8); acpi_os_read_port (acpi_gbl_gpe_registers[i].enable_addr, &acpi_gbl_gpe_registers[i].enable, 8); ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "GPE block at %X - Enable %08X Status %08X\n", acpi_gbl_gpe_registers[i].enable_addr, acpi_gbl_gpe_registers[i].status, acpi_gbl_gpe_registers[i].enable)); /* First check if there is anything active at all in this register */ enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status & acpi_gbl_gpe_registers[i].enable); if (!enabled_status_byte) { /* No active GPEs in this register, move on */ continue; } /* Now look at the individual GPEs in this byte register */ for (j = 0, bit_mask = 1; j < 8; j++, bit_mask <<= 1) { /* Examine one GPE bit */ if (enabled_status_byte & bit_mask) { /* * Found an active GPE. Dispatch the event to a handler * or method. */ int_status |= acpi_ev_gpe_dispatch ( acpi_gbl_gpe_registers[i].gpe_base + j); } } } return (int_status);}/******************************************************************************* * * FUNCTION: Acpi_ev_asynch_execute_gpe_method * * PARAMETERS: Gpe_number - The 0-based Gpe number * * RETURN: None * * DESCRIPTION: Perform the actual execution of a GPE control method. This * function is called from an invocation of Acpi_os_queue_for_execution * (and therefore does NOT execute at interrupt level) so that * the control method itself is not executed in the context of * the SCI interrupt handler. * ******************************************************************************/static voidacpi_ev_asynch_execute_gpe_method ( void *context){ u32 gpe_number = (u32) context; acpi_gpe_level_info gpe_info; FUNCTION_TRACE ("Ev_asynch_execute_gpe_method"); /* * Take a snapshot of the GPE info for this level */ acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); gpe_info = acpi_gbl_gpe_info [gpe_number]; acpi_ut_release_mutex (ACPI_MTX_EVENTS); /* * Method Handler (_Lxx, _Exx): * ---------------------------- * Evaluate the _Lxx/_Exx control method that corresponds to this GPE. */ if (gpe_info.method_handle) { acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); } /* * Level-Triggered? * ---------------- * If level-triggered we clear the GPE status bit after handling the event. */ if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } /* * Enable the GPE. */ acpi_hw_enable_gpe (gpe_number); return_VOID;}/******************************************************************************* * * FUNCTION: Acpi_ev_gpe_dispatch * * PARAMETERS: Gpe_number - The 0-based Gpe number * * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event. * Clears the status bit for the requested event. * * TBD: [Investigate] is this still valid or necessary: * The Gpe handler differs from the fixed events in that it clears the enable * bit rather than the status bit to clear the interrupt. This allows * software outside of interrupt context to determine what caused the SCI and * dispatch the correct AML. * ******************************************************************************/u32acpi_ev_gpe_dispatch ( u32 gpe_number){ acpi_gpe_level_info gpe_info; FUNCTION_TRACE ("Ev_gpe_dispatch"); /* * Valid GPE number? */ if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid GPE bit [%X].\n", gpe_number)); return_VALUE (INTERRUPT_NOT_HANDLED); } /* * Disable the GPE. */ acpi_hw_disable_gpe (gpe_number); gpe_info = acpi_gbl_gpe_info [gpe_number]; /* * Edge-Triggered? * --------------- * If edge-triggered, clear the GPE status bit now. Note that * level-triggered events are cleared after the GPE is serviced. */ if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } /* * Function Handler (e.g. EC)? */ if (gpe_info.handler) { /* Invoke function handler (at interrupt level). */ gpe_info.handler (gpe_info.context); /* Level-Triggered? */ if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } /* Enable GPE */ acpi_hw_enable_gpe (gpe_number); } /* * Method Handler (e.g. _Exx/_Lxx)? */ else if (gpe_info.method_handle) { if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE, acpi_ev_asynch_execute_gpe_method, (void*) gpe_number))) { /* * Shoudn't occur, but if it does report an error. Note that * the GPE will remain disabled until the ACPI Core Subsystem * is restarted, or the handler is removed/reinstalled. */ REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number)); } } /* * No Handler? Report an error and leave the GPE disabled. */ else { REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number)); /* Level-Triggered? */ if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { acpi_hw_clear_gpe (gpe_number); } } return_VALUE (INTERRUPT_HANDLED);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -