📄 evgpeblk.c
字号:
goto error_exit; } /* Save the new Info arrays in the GPE block */ gpe_block->register_info = gpe_register_info; gpe_block->event_info = gpe_event_info; /* * Initialize the GPE Register and Event structures. A goal of these * tables is to hide the fact that there are two separate GPE register sets * in a given gpe hardware block, the status registers occupy the first half, * and the enable registers occupy the second half. */ this_register = gpe_register_info; this_event = gpe_event_info; for (i = 0; i < gpe_block->register_count; i++) { /* Init the register_info for this GPE register (8 GPEs) */ this_register->base_gpe_number = (u8) (gpe_block->block_base_number + (i * ACPI_GPE_REGISTER_WIDTH)); ACPI_STORE_ADDRESS(this_register->status_address.address, (gpe_block->block_address.address + i)); ACPI_STORE_ADDRESS(this_register->enable_address.address, (gpe_block->block_address.address + i + gpe_block->register_count)); this_register->status_address.address_space_id = gpe_block->block_address.address_space_id; this_register->enable_address.address_space_id = gpe_block->block_address.address_space_id; this_register->status_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH; this_register->enable_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH; this_register->status_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH; this_register->enable_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH; /* Init the event_info for each GPE within this register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { this_event->register_bit = acpi_gbl_decode_to8bit[j]; this_event->register_info = this_register; this_event++; } /* * Clear the status/enable registers. Note that status registers * are cleared by writing a '1', while enable registers are cleared * by writing a '0'. */ status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00, &this_register-> enable_address); if (ACPI_FAILURE(status)) { goto error_exit; } status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF, &this_register-> status_address); if (ACPI_FAILURE(status)) { goto error_exit; } this_register++; } return_ACPI_STATUS(AE_OK); error_exit: if (gpe_register_info) { ACPI_MEM_FREE(gpe_register_info); } if (gpe_event_info) { ACPI_MEM_FREE(gpe_event_info); } return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION: acpi_ev_create_gpe_block * * PARAMETERS: gpe_device - Handle to the parent GPE block * gpe_block_address - Address and space_iD * register_count - Number of GPE register pairs in the block * gpe_block_base_number - Starting GPE number for the block * interrupt_number - H/W interrupt for the block * return_gpe_block - Where the new block descriptor is returned * * RETURN: Status * * DESCRIPTION: Create and Install a block of GPE registers * ******************************************************************************/acpi_statusacpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, struct acpi_generic_address *gpe_block_address, u32 register_count, u8 gpe_block_base_number, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block){ struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_event_info *gpe_event_info; acpi_native_uint i; acpi_native_uint j; u32 wake_gpe_count; u32 gpe_enabled_count; acpi_status status; struct acpi_gpe_walk_info gpe_info; ACPI_FUNCTION_TRACE("ev_create_gpe_block"); if (!register_count) { return_ACPI_STATUS(AE_OK); } /* Allocate a new GPE block */ gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info)); if (!gpe_block) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Initialize the new GPE block */ gpe_block->register_count = register_count; gpe_block->block_base_number = gpe_block_base_number; gpe_block->node = gpe_device; ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address, sizeof(struct acpi_generic_address)); /* Create the register_info and event_info sub-structures */ status = acpi_ev_create_gpe_info_blocks(gpe_block); if (ACPI_FAILURE(status)) { ACPI_MEM_FREE(gpe_block); return_ACPI_STATUS(status); } /* Install the new block in the global list(s) */ status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); if (ACPI_FAILURE(status)) { ACPI_MEM_FREE(gpe_block); return_ACPI_STATUS(status); } /* Find all GPE methods (_Lxx, _Exx) for this block */ status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info, gpe_block, NULL); /* * Runtime option: Should Wake GPEs be enabled at runtime? The default * is No, they should only be enabled just as the machine goes to sleep. */ if (acpi_gbl_leave_wake_gpes_disabled) { /* * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. * (Each GPE that has one or more _PRWs that reference it is by * definition a WAKE GPE and will not be enabled while the machine * is running.) */ gpe_info.gpe_block = gpe_block; gpe_info.gpe_device = gpe_device; status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe, &gpe_info, NULL); } /* * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs, * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must * be enabled via the acpi_enable_gpe() external interface. */ wake_gpe_count = 0; gpe_enabled_count = 0; for (i = 0; i < gpe_block->register_count; i++) { for (j = 0; j < 8; j++) { /* Get the info block for this particular GPE */ gpe_event_info = &gpe_block-> event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j]; if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) && (gpe_event_info-> flags & ACPI_GPE_TYPE_RUNTIME)) { gpe_enabled_count++; } if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) { wake_gpe_count++; } } } /* Dump info about this GPE block */ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", (u32) gpe_block->block_base_number, (u32) (gpe_block->block_base_number + ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) - 1)), gpe_device->name.ascii, gpe_block->register_count, interrupt_number)); /* Enable all valid GPEs found above */ status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block); ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Found %u Wake, Enabled %u Runtime GPEs in this block\n", wake_gpe_count, gpe_enabled_count)); /* Return the new block */ if (return_gpe_block) { (*return_gpe_block) = gpe_block; } return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_gpe_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Initialize the GPE data structures * ******************************************************************************/acpi_status acpi_ev_gpe_initialize(void){ u32 register_count0 = 0; u32 register_count1 = 0; u32 gpe_number_max = 0; acpi_status status; ACPI_FUNCTION_TRACE("ev_gpe_initialize"); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Initialize the GPE Block(s) defined in the FADT * * Why the GPE register block lengths are divided by 2: From the ACPI Spec, * section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN * The length of the GPE1_STS and GPE1_EN registers is equal to * half the GPE1_LEN. If a generic register block is not supported * then its respective block pointer and block length values in the * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need * to be the same size." */ /* * Determine the maximum GPE number for this machine. * * Note: both GPE0 and GPE1 are optional, and either can exist without * the other. * * If EITHER the register length OR the block address are zero, then that * particular block is not supported. */ if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) { /* GPE block 0 exists (has both length and address > 0) */ register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2); gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; /* Install GPE Block 0 */ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe0_blk, register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]); if (ACPI_FAILURE(status)) { ACPI_REPORT_ERROR(("Could not create GPE Block 0, %s\n", acpi_format_exception(status))); } } if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) { /* GPE block 1 exists (has both length and address > 0) */ register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2); /* Check for GPE0/GPE1 overlap (if both banks exist) */ if ((register_count0) && (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) { ACPI_REPORT_ERROR(("GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n", gpe_number_max, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1))); /* Ignore GPE1 block by setting the register count to zero */ register_count1 = 0; } else { /* Install GPE Block 1 */ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT->xgpe1_blk, register_count1, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks [1]); if (ACPI_FAILURE(status)) { ACPI_REPORT_ERROR(("Could not create GPE Block 1, %s\n", acpi_format_exception(status))); } /* * GPE0 and GPE1 do not have to be contiguous in the GPE number * space. However, GPE0 always starts at GPE number zero. */ gpe_number_max = acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); } } /* Exit if there are no GPE registers */ if ((register_count0 + register_count1) == 0) { /* GPEs are not required by ACPI, this is OK */ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "There are no GPE blocks defined in the FADT\n")); status = AE_OK; goto cleanup; } /* Check for Max GPE number out-of-range */ if (gpe_number_max > ACPI_GPE_MAX) { ACPI_REPORT_ERROR(("Maximum GPE number from FADT is too large: 0x%X\n", gpe_number_max)); status = AE_BAD_VALUE; goto cleanup; } cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -