/******************************************************************************* * * FUNCTION: acpi_install_gpe_block * * PARAMETERS: gpe_device - Handle to the parent GPE Block Device * gpe_block_address - Address and space_iD * register_count - Number of GPE register pairs in the block * interrupt_number - H/W interrupt for the block * * RETURN: Status * * DESCRIPTION: Create and Install a block of GPE registers * ******************************************************************************/ acpi_status acpi_install_gpe_block(acpi_handle gpe_device, struct acpi_generic_address *gpe_block_address, u32 register_count, u32 interrupt_number) { acpi_status status; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; struct acpi_gpe_block_info *gpe_block; ACPI_FUNCTION_TRACE(acpi_install_gpe_block); if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); } node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* * For user-installed GPE Block Devices, the gpe_block_base_number * is always zero */ status = acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, interrupt_number, &gpe_block); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } /* Install block in the device_object attached to the node */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { /* * No object, create a new one (Device nodes do not always have * an attached object) */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); /* Remove local reference to the object */ acpi_ut_remove_reference(obj_desc); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } /* Now install the GPE block in the device_object */ obj_desc->device.gpe_block = gpe_block; /* Enable the runtime GPEs in the new block */ status = acpi_ev_initialize_gpe_block(node, gpe_block); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); }
acpi_status acpi_ev_gpe_initialize (void) { u32 register_count0 = 0; u32 register_count1 = 0; u32 gpe_number_max = 0; acpi_handle gpe_device; acpi_status status; ACPI_FUNCTION_TRACE ("ev_gpe_initialize"); /* Get a handle to the predefined _GPE object */ status = acpi_get_handle (NULL, "\\_GPE", &gpe_device); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* * Initialize the GPE Blocks 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 (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 (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_REPORT_INFO (("There are no GPE blocks defined in the FADT\n")); return_ACPI_STATUS (AE_OK); } /* 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)); return_ACPI_STATUS (AE_BAD_VALUE); } return_ACPI_STATUS (AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_ev_gpe_initialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks * ******************************************************************************/ 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); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Initializing General Purpose Events (GPEs):\n")); 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_block_length && acpi_gbl_FADT.xgpe0_block.address) { /* GPE block 0 exists (has both length and address > 0) */ register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 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_block. address, acpi_gbl_FADT.xgpe0_block. space_id, register_count0, 0, acpi_gbl_FADT.sci_interrupt, &acpi_gbl_gpe_fadt_blocks[0]); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create GPE Block 0")); } } if (acpi_gbl_FADT.gpe1_block_length && acpi_gbl_FADT.xgpe1_block.address) { /* GPE block 1 exists (has both length and address > 0) */ register_count1 = (u16)(acpi_gbl_FADT.gpe1_block_length / 2); /* Check for GPE0/GPE1 overlap (if both banks exist) */ if ((register_count0) && (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { ACPI_ERROR((AE_INFO, "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " "(GPE %u to %u) - Ignoring GPE1", 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_block. address, acpi_gbl_FADT.xgpe1_block. space_id, register_count1, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT. sci_interrupt, &acpi_gbl_gpe_fadt_blocks [1]); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create GPE Block 1")); } /* * 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; } cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK); }
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); } if (acpi_gbl_FADT.gpe0_block_length && acpi_gbl_FADT.xgpe0_block.address) { register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2); gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT.xgpe0_block, register_count0, 0, acpi_gbl_FADT.sci_interrupt, &acpi_gbl_gpe_fadt_blocks[0]); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create GPE Block 0")); } } if (acpi_gbl_FADT.gpe1_block_length && acpi_gbl_FADT.xgpe1_block.address) { register_count1 = (u16)(acpi_gbl_FADT.gpe1_block_length / 2); if ((register_count0) && (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { ACPI_ERROR((AE_INFO, "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " "(GPE %u to %u) - Ignoring GPE1", gpe_number_max, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT.gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1))); register_count1 = 0; } else { status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, &acpi_gbl_FADT.xgpe1_block, register_count1, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT. sci_interrupt, &acpi_gbl_gpe_fadt_blocks [1]); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create GPE Block 1")); } gpe_number_max = acpi_gbl_FADT.gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); } } if ((register_count0 + register_count1) == 0) { ACPI_DEBUG_PRINT((ACPI_DB_INIT, "There are no GPE blocks defined in the FADT\n")); status = AE_OK; goto cleanup; } if (gpe_number_max > ACPI_GPE_MAX) { ACPI_ERROR((AE_INFO, "Maximum GPE number from FADT is too large: 0x%X", gpe_number_max)); status = AE_BAD_VALUE; goto cleanup; } cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK); }