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

📄 evevent.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * by writing a '0'.
		 */
		acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00);
		acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF);

		register_index++;
	}

	/* 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_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00);
		acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF);

		register_index++;
	}

	return (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_STATUS
acpi_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;


	/* 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! */

		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 */

		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);

	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_STATUS
acpi_ev_init_gpe_control_methods (void)
{
	ACPI_STATUS             status;


	/* Get a permanent handle to the _GPE object */

	status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle);
	if (ACPI_FAILURE (status)) {
		return (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 (status);
}


/******************************************************************************
 *
 * FUNCTION:    Acpi_ev_gpe_detect
 *
 * PARAMETERS:  None
 *
 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
 *
 * DESCRIPTION: Detect if any GP events have occurred
 *
 ******************************************************************************/

u32
acpi_ev_gpe_detect (void)
{
	u32                     int_status = INTERRUPT_NOT_HANDLED;
	u32                     i;
	u32                     j;
	u8                      enabled_status_byte;
	u8                      bit_mask;


	/*
	 * 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_gbl_gpe_registers[i].status =
				   acpi_os_in8 (acpi_gbl_gpe_registers[i].status_addr);

		acpi_gbl_gpe_registers[i].enable =
				   acpi_os_in8 (acpi_gbl_gpe_registers[i].enable_addr);

		/* 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 void
acpi_ev_asynch_execute_gpe_method (
	void                    *context)
{
	u32                     gpe_number = (u32) context;
	ACPI_GPE_LEVEL_INFO     gpe_info;


	/*
	 * Take a snapshot of the GPE info for this level
	 */
	acpi_cm_acquire_mutex (ACPI_MTX_EVENTS);
	gpe_info = acpi_gbl_gpe_info [gpe_number];
	acpi_cm_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;
}


/******************************************************************************
 *
 * 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.
 *
 ******************************************************************************/

u32
acpi_ev_gpe_dispatch (
	u32                     gpe_number)
{
	ACPI_GPE_LEVEL_INFO     gpe_info;

	/*
	 * Valid GPE number?
	 */
	if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
		return (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*)(NATIVE_UINT)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 (INTERRUPT_HANDLED);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -