⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evgpeblk.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -