185835Siwasaki/*- 285835Siwasaki * Copyright (c) 2001 Mitsuru IWASAKI 385835Siwasaki * All rights reserved. 485835Siwasaki * 585835Siwasaki * Redistribution and use in source and binary forms, with or without 685835Siwasaki * modification, are permitted provided that the following conditions 785835Siwasaki * are met: 885835Siwasaki * 1. Redistributions of source code must retain the above copyright 985835Siwasaki * notice, this list of conditions and the following disclaimer. 1085835Siwasaki * 2. Redistributions in binary form must reproduce the above copyright 1185835Siwasaki * notice, this list of conditions and the following disclaimer in the 1285835Siwasaki * documentation and/or other materials provided with the distribution. 1385835Siwasaki * 1485835Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1585835Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1685835Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1785835Siwasaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1885835Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1985835Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2085835Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2185835Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2285835Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2385835Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2485835Siwasaki * SUCH DAMAGE. 2585835Siwasaki */ 2685835Siwasaki 27116182Sobrien#include <sys/cdefs.h> 28116182Sobrien__FBSDID("$FreeBSD$"); 29116182Sobrien 3085835Siwasaki#include <sys/param.h> 3185835Siwasaki#include <sys/systm.h> 3291640Siwasaki#include <sys/proc.h> 3385835Siwasaki 3485835Siwasaki#include <sys/power.h> 35152222Simp#include <sys/taskqueue.h> 3685835Siwasaki 3785835Siwasakistatic u_int power_pm_type = POWER_PM_TYPE_NONE; 3885835Siwasakistatic power_pm_fn_t power_pm_fn = NULL; 3985835Siwasakistatic void *power_pm_arg = NULL; 40152222Simpstatic struct task power_pm_task; 4185835Siwasaki 42152222Simpstatic void 43152222Simppower_pm_deferred_fn(void *arg, int pending) 44152222Simp{ 45152246Sjhb int state = (intptr_t)arg; 46152222Simp 47152222Simp power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state); 48152222Simp} 49152222Simp 5085835Siwasakiint 5185835Siwasakipower_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg) 5285835Siwasaki{ 5385835Siwasaki int error; 5485835Siwasaki 5585835Siwasaki if (power_pm_type == POWER_PM_TYPE_NONE || 5685835Siwasaki power_pm_type == pm_type) { 5785835Siwasaki power_pm_type = pm_type; 5885835Siwasaki power_pm_fn = pm_fn; 5985835Siwasaki power_pm_arg = pm_arg; 6085835Siwasaki error = 0; 61152222Simp TASK_INIT(&power_pm_task, 0, power_pm_deferred_fn, NULL); 6285835Siwasaki } else { 6385835Siwasaki error = ENXIO; 6485835Siwasaki } 6585835Siwasaki 6685835Siwasaki return (error); 6785835Siwasaki} 6885835Siwasaki 6985835Siwasakiu_int 7085835Siwasakipower_pm_get_type(void) 7185835Siwasaki{ 7285835Siwasaki 7385835Siwasaki return (power_pm_type); 7485835Siwasaki} 7585835Siwasaki 7685835Siwasakivoid 7785835Siwasakipower_pm_suspend(int state) 7885835Siwasaki{ 7985835Siwasaki if (power_pm_fn == NULL) 8085835Siwasaki return; 8185835Siwasaki 8285835Siwasaki if (state != POWER_SLEEP_STATE_STANDBY && 8385835Siwasaki state != POWER_SLEEP_STATE_SUSPEND && 8485835Siwasaki state != POWER_SLEEP_STATE_HIBERNATE) 8585835Siwasaki return; 86152246Sjhb power_pm_task.ta_context = (void *)(intptr_t)state; 87152248Simp taskqueue_enqueue(taskqueue_thread, &power_pm_task); 8885835Siwasaki} 8985835Siwasaki 9091640Siwasaki/* 9191640Siwasaki * Power profile. 9291640Siwasaki */ 9391640Siwasaki 9491640Siwasakistatic int power_profile_state = POWER_PROFILE_PERFORMANCE; 9591640Siwasaki 9691640Siwasakiint 9791640Siwasakipower_profile_get_state(void) 9891640Siwasaki{ 9991640Siwasaki return (power_profile_state); 10091640Siwasaki} 10191640Siwasaki 10291640Siwasakivoid 10391640Siwasakipower_profile_set_state(int state) 10491640Siwasaki{ 10591640Siwasaki int changed; 10691640Siwasaki 10791640Siwasaki if (state != power_profile_state) { 10891640Siwasaki power_profile_state = state; 10991640Siwasaki changed = 1; 110124079Snjl if (bootverbose) { 111124079Snjl printf("system power profile changed to '%s'\n", 112124079Snjl (state == POWER_PROFILE_PERFORMANCE) ? 113124079Snjl "performance" : "economy"); 114124079Snjl } 11591640Siwasaki } else { 11691640Siwasaki changed = 0; 11791640Siwasaki } 11891640Siwasaki 11991640Siwasaki if (changed) 120100112Smarkm EVENTHANDLER_INVOKE(power_profile_change, 0); 12191640Siwasaki} 12291640Siwasaki 123