📄 evgpeblk.c
字号:
/* * The _PRW object must return a package, we are only interested * in the first element */ obj_desc = pkg_desc->package.elements[0]; if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Use FADT-defined GPE device (from definition of _PRW) */ target_gpe_device = acpi_gbl_fadt_gpe_device; /* Integer is the GPE number in the FADT described GPE blocks */ gpe_number = (u32) obj_desc->integer.value; } else if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { /* Package contains a GPE reference and GPE number within a GPE block */ if ((obj_desc->package.count < 2) || (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) || (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) { goto cleanup; } /* Get GPE block reference and decode */ target_gpe_device = obj_desc->package.elements[0]->reference.node; gpe_number = (u32) obj_desc->package.elements[1]->integer.value; } else { /* Unknown type, just ignore it */ goto cleanup; } /* * Is this GPE within this block? * * TRUE iff these conditions are true: * 1) The GPE devices match. * 2) The GPE index(number) is within the range of the Gpe Block * associated with the GPE device. */ if ((gpe_device == target_gpe_device) && (gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE); if (ACPI_FAILURE (status)) { goto cleanup; } status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE); }cleanup: acpi_ut_remove_reference (pkg_desc); return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_get_gpe_xrupt_block * * PARAMETERS: interrupt_level - Interrupt for a GPE block * * RETURN: A GPE interrupt block * * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt * block per unique interrupt level used for GPEs. * Should be called only when the GPE lists are semaphore locked * and not subject to change. * ******************************************************************************/static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block ( u32 interrupt_level){ struct acpi_gpe_xrupt_info *next_gpe_xrupt; struct acpi_gpe_xrupt_info *gpe_xrupt; acpi_status status; ACPI_FUNCTION_TRACE ("ev_get_gpe_xrupt_block"); /* No need for spin lock since we are not changing any list elements here */ next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt) { if (next_gpe_xrupt->interrupt_level == interrupt_level) { return_PTR (next_gpe_xrupt); } next_gpe_xrupt = next_gpe_xrupt->next; } /* Not found, must allocate a new xrupt descriptor */ gpe_xrupt = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_xrupt_info)); if (!gpe_xrupt) { return_PTR (NULL); } gpe_xrupt->interrupt_level = interrupt_level; /* Install new interrupt descriptor with spin lock */ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); if (acpi_gbl_gpe_xrupt_list_head) { next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt->next) { next_gpe_xrupt = next_gpe_xrupt->next; } next_gpe_xrupt->next = gpe_xrupt; gpe_xrupt->previous = next_gpe_xrupt; } else { acpi_gbl_gpe_xrupt_list_head = gpe_xrupt; } acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); /* Install new interrupt handler if not SCI_INT */ if (interrupt_level != acpi_gbl_FADT->sci_int) { status = acpi_os_install_interrupt_handler (interrupt_level, acpi_ev_gpe_xrupt_handler, gpe_xrupt); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not install GPE interrupt handler at level 0x%X\n", interrupt_level)); return_PTR (NULL); } } return_PTR (gpe_xrupt);}/******************************************************************************* * * FUNCTION: acpi_ev_delete_gpe_xrupt * * PARAMETERS: gpe_xrupt - A GPE interrupt info block * * RETURN: Status * * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated * interrupt handler if not the SCI interrupt. * ******************************************************************************/static acpi_statusacpi_ev_delete_gpe_xrupt ( struct acpi_gpe_xrupt_info *gpe_xrupt){ acpi_status status; ACPI_FUNCTION_TRACE ("ev_delete_gpe_xrupt"); /* We never want to remove the SCI interrupt handler */ if (gpe_xrupt->interrupt_level == acpi_gbl_FADT->sci_int) { gpe_xrupt->gpe_block_list_head = NULL; return_ACPI_STATUS (AE_OK); } /* Disable this interrupt */ status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_level, acpi_ev_gpe_xrupt_handler); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Unlink the interrupt block with lock */ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); if (gpe_xrupt->previous) { gpe_xrupt->previous->next = gpe_xrupt->next; } if (gpe_xrupt->next) { gpe_xrupt->next->previous = gpe_xrupt->previous; } acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); /* Free the block */ ACPI_MEM_FREE (gpe_xrupt); return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_install_gpe_block * * PARAMETERS: gpe_block - New GPE block * interrupt_level - Level to be associated with this GPE block * * RETURN: Status * * DESCRIPTION: Install new GPE block with mutex support * ******************************************************************************/static acpi_statusacpi_ev_install_gpe_block ( struct acpi_gpe_block_info *gpe_block, u32 interrupt_level){ struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_block; acpi_status status; ACPI_FUNCTION_TRACE ("ev_install_gpe_block"); status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level); if (!gpe_xrupt_block) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Install the new block at the end of the list for this interrupt with lock */ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); if (gpe_xrupt_block->gpe_block_list_head) { next_gpe_block = gpe_xrupt_block->gpe_block_list_head; while (next_gpe_block->next) { next_gpe_block = next_gpe_block->next; } next_gpe_block->next = gpe_block; gpe_block->previous = next_gpe_block; } else { gpe_xrupt_block->gpe_block_list_head = gpe_block; } gpe_block->xrupt_block = gpe_xrupt_block; acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);unlock_and_exit: status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: acpi_ev_delete_gpe_block * * PARAMETERS: gpe_block - Existing GPE block * * RETURN: Status * * DESCRIPTION: Remove a GPE block * ******************************************************************************/acpi_statusacpi_ev_delete_gpe_block ( struct acpi_gpe_block_info *gpe_block){ acpi_status status; ACPI_FUNCTION_TRACE ("ev_install_gpe_block"); status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Disable all GPEs in this block */ status = acpi_hw_disable_gpe_block (gpe_block->xrupt_block, gpe_block); if (!gpe_block->previous && !gpe_block->next) { /* This is the last gpe_block on this interrupt */ status = acpi_ev_delete_gpe_xrupt (gpe_block->xrupt_block); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } } else { /* Remove the block on this interrupt with lock */ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); if (gpe_block->previous) { gpe_block->previous->next = gpe_block->next; } else { gpe_block->xrupt_block->gpe_block_list_head = gpe_block->next; } if (gpe_block->next) { gpe_block->next->previous = gpe_block->previous; } acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); } /* Free the gpe_block */ ACPI_MEM_FREE (gpe_block->register_info); ACPI_MEM_FREE (gpe_block->event_info); ACPI_MEM_FREE (gpe_block);unlock_and_exit: status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: acpi_ev_create_gpe_info_blocks * * PARAMETERS: gpe_block - New GPE block * * RETURN: Status * * DESCRIPTION: Create the register_info and event_info blocks for this GPE block * ******************************************************************************/static acpi_statusacpi_ev_create_gpe_info_blocks ( struct acpi_gpe_block_info *gpe_block){ struct acpi_gpe_register_info *gpe_register_info = NULL; struct acpi_gpe_event_info *gpe_event_info = NULL; struct acpi_gpe_event_info *this_event; struct acpi_gpe_register_info *this_register; acpi_native_uint i; acpi_native_uint j; acpi_status status; ACPI_FUNCTION_TRACE ("ev_create_gpe_info_blocks"); /* Allocate the GPE register information block */ gpe_register_info = ACPI_MEM_CALLOCATE ( (acpi_size) gpe_block->register_count * sizeof (struct acpi_gpe_register_info)); if (!gpe_register_info) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the gpe_register_info table\n")); return_ACPI_STATUS (AE_NO_MEMORY); } /* * Allocate the GPE event_info block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ gpe_event_info = ACPI_MEM_CALLOCATE ( ((acpi_size) gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) * sizeof (struct acpi_gpe_event_info)); if (!gpe_event_info) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the gpe_event_info table\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -