u32 acpi_hw_get_mode (void) { acpi_status status; u32 value; ACPI_FUNCTION_TRACE ("hw_get_mode"); /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. */ if (!acpi_gbl_FADT->smi_cmd) { return_VALUE (ACPI_SYS_MODE_ACPI); } status = acpi_get_register (ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE (status)) { return_VALUE (ACPI_SYS_MODE_LEGACY); } if (value) { return_VALUE (ACPI_SYS_MODE_ACPI); } else { return_VALUE (ACPI_SYS_MODE_LEGACY); } }
static int acpi_idle_bm_check(void) { u32 bm_status = 0; acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); if ( bm_status ) acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); /* * TBD: PIIX4 Erratum #18: Note that BM_STS doesn't always reflect * the true state of bus mastering activity; forcing us to * manually check the BMIDEA bit of each IDE channel. */ return bm_status; }
acpi_status asmlinkage acpi_enter_sleep_state_s4bios ( void) { u32 in_value; acpi_status status; ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_s4bios"); status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ status = acpi_hw_disable_all_gpes (ACPI_ISR); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } acpi_gbl_system_awake_and_running = FALSE; status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } ACPI_FLUSH_CPU_CACHE (); status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, (u32) acpi_gbl_FADT->S4bios_req, 8); do { acpi_os_stall(1000); status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } while (!in_value); return_ACPI_STATUS (AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_enable_event * * PARAMETERS: Event - The fixed eventto be enabled * Flags - Reserved * * RETURN: Status * * DESCRIPTION: Enable an ACPI event (fixed) * ******************************************************************************/ acpi_status acpi_enable_event(u32 event, u32 flags) { acpi_status status = AE_OK; u32 value; ACPI_FUNCTION_TRACE(acpi_enable_event); /* Decode the Fixed Event */ if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Enable the requested fixed event (by writing a one to the * enable register bit) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. enable_register_id, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Make sure that the hardware responded */ status = acpi_get_register(acpi_gbl_fixed_event_info[event]. enable_register_id, &value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (value != 1) { ACPI_ERROR((AE_INFO, "Could not enable %s event", acpi_ut_get_event_name(event))); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_disable_event * * PARAMETERS: Event - The fixed eventto be enabled * Flags - Reserved * * RETURN: Status * * DESCRIPTION: Disable an ACPI event (fixed) * ******************************************************************************/ acpi_status acpi_disable_event(u32 event, u32 flags) { acpi_status status = AE_OK; u32 value; ACPI_FUNCTION_TRACE(acpi_disable_event); /* Decode the Fixed Event */ if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Disable the requested fixed event (by writing a zero to the * enable register bit) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. enable_register_id, 0, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_get_register(acpi_gbl_fixed_event_info[event]. enable_register_id, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (value != 0) { ACPI_ERROR((AE_INFO, "Could not disable %s events", acpi_ut_get_event_name(event))); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); } return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_get_event_status * * PARAMETERS: Event - The fixed event * event_status - Where the current status of the event will * be returned * * RETURN: Status * * DESCRIPTION: Obtains and returns the current status of the event * ******************************************************************************/ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(acpi_get_event_status); if (!event_status) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Decode the Fixed Event */ if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Get the status of the requested fixed event */ status = acpi_get_register(acpi_gbl_fixed_event_info[event]. status_register_id, event_status); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_enter_sleep_state * * PARAMETERS: sleep_state - Which sleep state to enter * * RETURN: Status * * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) { u32 PM1Acontrol; u32 PM1Bcontrol; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; #if !(defined(CONFIG_XEN) && defined(CONFIG_X86)) u32 in_value; #else int err; #endif acpi_status status; ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X", acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } sleep_type_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); /* Clear wake status */ status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Clear all fixed and general purpose status bits */ status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ status = acpi_hw_disable_all_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } acpi_gbl_system_awake_and_running = FALSE; status = acpi_hw_enable_all_wakeup_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Entering sleep state [S%d]\n", sleep_state)); /* Clear SLP_EN and SLP_TYP fields */ PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info->access_bit_mask); PM1Bcontrol = PM1Acontrol; /* Insert SLP_TYP bits */ PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); /* * We split the writes of SLP_TYP and SLP_EN to workaround * poorly implemented hardware. */ /* Write #1: fill in SLP_TYP data */ status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Insert SLP_ENABLE bit */ PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; /* Write #2: SLP_TYP + SLP_EN */ ACPI_FLUSH_CPU_CACHE(); #if !(defined(CONFIG_XEN) && defined(CONFIG_X86)) status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (sleep_state > ACPI_STATE_S3) { /* * We wanted to sleep > S3, but it didn't happen (by virtue of the * fact that we are still executing!) * * Wait ten seconds, then try again. This is to get S4/S5 to work on * all machines. * * We wait so long to allow chipsets that poll this reg very slowly to * still read the right value. Ideally, this block would go * away entirely. */ acpi_os_stall(10000000); status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info-> access_bit_mask); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Wait until we enter sleep state */ do { status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Spin until we wake */ } while (!in_value); #else /* PV ACPI just need check hypercall return value */ err = acpi_notify_hypervisor_state(sleep_state, PM1Acontrol, PM1Bcontrol); if (err) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hypervisor failure [%d]\n", err)); return_ACPI_STATUS(AE_ERROR); } #endif return_ACPI_STATUS(AE_OK); }
acpi_status asmlinkage acpi_enter_sleep_state ( u8 sleep_state) { u32 PM1Acontrol; u32 PM1Bcontrol; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 in_value; acpi_status status; ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state"); if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n", acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A); sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE); if (sleep_state != ACPI_STATE_S5) { /* Clear wake status */ status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Disable BM arbitration */ status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } /* * 1) Disable all runtime GPEs * 2) Enable all wakeup GPEs */ status = acpi_hw_prepare_gpes_for_sleep (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Get current value of PM1A control */ status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Entering sleep state [S%d]\n", sleep_state)); /* Clear SLP_EN and SLP_TYP fields */ PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | sleep_enable_reg_info->access_bit_mask); PM1Bcontrol = PM1Acontrol; /* Insert SLP_TYP bits */ PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); /* * We split the writes of SLP_TYP and SLP_EN to workaround * poorly implemented hardware. */ /* Write #1: fill in SLP_TYP data */ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Insert SLP_ENABLE bit */ PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; /* Write #2: SLP_TYP + SLP_EN */ ACPI_FLUSH_CPU_CACHE (); status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } if (sleep_state > ACPI_STATE_S3) { /* * We wanted to sleep > S3, but it didn't happen (by virtue of the fact that * we are still executing!) * * Wait ten seconds, then try again. This is to get S4/S5 to work on all machines. * * We wait so long to allow chipsets that poll this reg very slowly to * still read the right value. Ideally, this block would go * away entirely. */ acpi_os_stall (10000000); status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info->access_bit_mask); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } /* Wait until we enter sleep state */ do { status = acpi_get_register (ACPI_BITREG_WAKE_STATUS, &in_value, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Spin until we wake */ } while (!in_value); return_ACPI_STATUS (AE_OK); }