Style and whitespace changes. Also, make the ivar functions non-inline

since inlining failed due to the size of BUS_*
This commit is contained in:
Nate Lawson 2003-08-28 16:06:30 +00:00
parent 772a9659d9
commit be2b179704
9 changed files with 1190 additions and 1153 deletions

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h> #include <sys/rman.h>
#include "acpi.h" #include "acpi.h"
#include <dev/acpica/acpivar.h> #include <dev/acpica/acpivar.h>
/* /*
@ -50,9 +49,7 @@ __FBSDID("$FreeBSD$");
* _PSS and _PPC. * _PSS and _PPC.
*/ */
/* /* Hooks for the ACPI CA debugging infrastructure */
* Hooks for the ACPI CA debugging infrastructure
*/
#define _COMPONENT ACPI_PROCESSOR #define _COMPONENT ACPI_PROCESSOR
ACPI_MODULE_NAME("PROCESSOR") ACPI_MODULE_NAME("PROCESSOR")
@ -64,15 +61,16 @@ struct acpi_cpu_softc {
/* CPU throttling control register */ /* CPU throttling control register */
struct resource *cpu_p_blk; struct resource *cpu_p_blk;
#define CPU_GET_P_CNT(sc) (bus_space_read_4(rman_get_bustag((sc)->cpu_p_blk), \ #define CPU_P_CNT_THT_EN (1<<4)
rman_get_bushandle((sc)->cpu_p_blk), \
0))
#define CPU_SET_P_CNT(sc, val) (bus_space_write_4(rman_get_bustag((sc)->cpu_p_blk), \
rman_get_bushandle((sc)->cpu_p_blk), \
0, (val)))
#define CPU_P_CNT_THT_EN (1<<4)
}; };
#define CPU_GET_P_CNT(sc) \
(bus_space_read_4(rman_get_bustag((sc)->cpu_p_blk), \
rman_get_bushandle((sc)->cpu_p_blk), 0))
#define CPU_SET_P_CNT(sc, val) \
(bus_space_write_4(rman_get_bustag((sc)->cpu_p_blk), \
rman_get_bushandle((sc)->cpu_p_blk), 0, (val)))
/* /*
* Speeds are stored in counts, from 1 - CPU_MAX_SPEED, and * Speeds are stored in counts, from 1 - CPU_MAX_SPEED, and
* reported to the user in tenths of a percent. * reported to the user in tenths of a percent.
@ -83,7 +81,8 @@ static u_int32_t cpu_duty_width;
#define CPU_SPEED_PERCENT(x) ((1000 * (x)) / CPU_MAX_SPEED) #define CPU_SPEED_PERCENT(x) ((1000 * (x)) / CPU_MAX_SPEED)
#define CPU_SPEED_PRINTABLE(x) (CPU_SPEED_PERCENT(x) / 10),(CPU_SPEED_PERCENT(x) % 10) #define CPU_SPEED_PRINTABLE(x) (CPU_SPEED_PERCENT(x) / 10),(CPU_SPEED_PERCENT(x) % 10)
static u_int32_t cpu_smi_cmd; /* should be a generic way to do this */ /* XXX Should be a generic way to do this */
static u_int32_t cpu_smi_cmd;
static u_int8_t cpu_pstate_cnt; static u_int8_t cpu_pstate_cnt;
static u_int32_t cpu_current_state; static u_int32_t cpu_current_state;
@ -124,12 +123,13 @@ DRIVER_MODULE(acpi_cpu, acpi, acpi_cpu_driver, acpi_cpu_devclass, 0, 0);
static int static int
acpi_cpu_probe(device_t dev) acpi_cpu_probe(device_t dev)
{ {
if (!acpi_disabled("cpu") && if (!acpi_disabled("cpu") && acpi_get_type(dev) == ACPI_TYPE_PROCESSOR) {
(acpi_get_type(dev) == ACPI_TYPE_PROCESSOR)) { /* XXX get more verbose description? */
device_set_desc(dev, "CPU"); /* XXX get more verbose description? */ device_set_desc(dev, "CPU");
return(0); return (0);
} }
return(ENXIO);
return (ENXIO);
} }
static int static int
@ -153,71 +153,79 @@ acpi_cpu_attach(device_t dev)
sc->cpu_dev = dev; sc->cpu_dev = dev;
sc->cpu_handle = acpi_get_handle(dev); sc->cpu_handle = acpi_get_handle(dev);
/* /* Get global parameters from the FADT. */
* Get global parameters from the FADT.
*/
if (device_get_unit(sc->cpu_dev) == 0) { if (device_get_unit(sc->cpu_dev) == 0) {
cpu_duty_offset = AcpiGbl_FADT->DutyOffset; cpu_duty_offset = AcpiGbl_FADT->DutyOffset;
cpu_duty_width = AcpiGbl_FADT->DutyWidth; cpu_duty_width = AcpiGbl_FADT->DutyWidth;
cpu_smi_cmd = AcpiGbl_FADT->SmiCmd; cpu_smi_cmd = AcpiGbl_FADT->SmiCmd;
cpu_pstate_cnt = AcpiGbl_FADT->PstateCnt; cpu_pstate_cnt = AcpiGbl_FADT->PstateCnt;
/* validate the offset/width */ /* Validate the offset/width */
if (cpu_duty_width > 0) { if (cpu_duty_width > 0) {
duty_end = cpu_duty_offset + cpu_duty_width - 1; duty_end = cpu_duty_offset + cpu_duty_width - 1;
/* check that it fits */
if (duty_end > 31) { /* Check that it fits */
printf("acpi_cpu: CLK_VAL field overflows P_CNT register\n"); if (duty_end > 31) {
cpu_duty_width = 0; printf("acpi_cpu: CLK_VAL field overflows P_CNT register\n");
} cpu_duty_width = 0;
/* check for overlap with the THT_EN bit */ }
if ((cpu_duty_offset <= 4) && (duty_end >= 4)) {
printf("acpi_cpu: CLK_VAL field overlaps THT_EN bit\n"); /* Check for overlap with the THT_EN bit */
cpu_duty_width = 0; if (cpu_duty_offset <= 4 && duty_end >= 4) {
} printf("acpi_cpu: CLK_VAL field overlaps THT_EN bit\n");
cpu_duty_width = 0;
}
} }
/* /*
* Start the throttling process once the probe phase completes, if we think that * Start the throttling process once the probe phase completes, if we
* it's going to be useful. If the duty width value is zero, there are no significant * think that it's going to be useful. If the duty width value is
* bits in the register and thus no throttled states. * zero, there are no significant bits in the register and thus no
* throttled states.
*/ */
if (cpu_duty_width > 0) { if (cpu_duty_width > 0) {
AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cpu_init_throttling, NULL); AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cpu_init_throttling,
NULL);
acpi_sc = acpi_device_get_parent_softc(dev); acpi_sc = acpi_device_get_parent_softc(dev);
sysctl_ctx_init(&acpi_cpu_sysctl_ctx); sysctl_ctx_init(&acpi_cpu_sysctl_ctx);
acpi_cpu_sysctl_tree = SYSCTL_ADD_NODE(&acpi_cpu_sysctl_ctx, acpi_cpu_sysctl_tree = SYSCTL_ADD_NODE(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
OID_AUTO, "cpu", CTLFLAG_RD, 0, ""); OID_AUTO, "cpu", CTLFLAG_RD, 0, "");
SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx, SYSCTL_CHILDREN(acpi_cpu_sysctl_tree), SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
OID_AUTO, "max_speed", CTLFLAG_RD, OID_AUTO, "max_speed", CTLFLAG_RD,
&cpu_max_state, 0, "maximum CPU speed"); &cpu_max_state, 0, "maximum CPU speed");
SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx, SYSCTL_CHILDREN(acpi_cpu_sysctl_tree), SYSCTL_ADD_INT(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
OID_AUTO, "current_speed", CTLFLAG_RD, OID_AUTO, "current_speed", CTLFLAG_RD,
&cpu_current_state, 0, "current CPU speed"); &cpu_current_state, 0, "current CPU speed");
SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx, SYSCTL_CHILDREN(acpi_cpu_sysctl_tree), SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
OID_AUTO, "performance_speed", CTLTYPE_INT | CTLFLAG_RW, SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
&cpu_performance_state, 0, acpi_cpu_speed_sysctl, "I", ""); OID_AUTO, "performance_speed",
SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx, SYSCTL_CHILDREN(acpi_cpu_sysctl_tree), CTLTYPE_INT | CTLFLAG_RW, &cpu_performance_state,
OID_AUTO, "economy_speed", CTLTYPE_INT | CTLFLAG_RW, 0, acpi_cpu_speed_sysctl, "I", "");
&cpu_economy_state, 0, acpi_cpu_speed_sysctl, "I", ""); SYSCTL_ADD_PROC(&acpi_cpu_sysctl_ctx,
SYSCTL_CHILDREN(acpi_cpu_sysctl_tree),
OID_AUTO, "economy_speed",
CTLTYPE_INT | CTLFLAG_RW, &cpu_economy_state,
0, acpi_cpu_speed_sysctl, "I", "");
} }
} }
/* /* Get the processor object. */
* Get the processor object.
*/
buf.Pointer = &processor; buf.Pointer = &processor;
buf.Length = sizeof(processor); buf.Length = sizeof(processor);
if (ACPI_FAILURE(status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf))) { status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
device_printf(sc->cpu_dev, "couldn't get Processor object - %s\n", AcpiFormatException(status)); if (ACPI_FAILURE(status)) {
return_VALUE(ENXIO); device_printf(sc->cpu_dev, "couldn't get Processor object - %s\n",
AcpiFormatException(status));
return_VALUE (ENXIO);
} }
if (processor.Type != ACPI_TYPE_PROCESSOR) { if (processor.Type != ACPI_TYPE_PROCESSOR) {
device_printf(sc->cpu_dev, "Processor object has bad type %d\n", processor.Type); device_printf(sc->cpu_dev, "Processor object has bad type %d\n",
return_VALUE(ENXIO); processor.Type);
return_VALUE (ENXIO);
} }
sc->cpu_id = processor.Processor.ProcId; sc->cpu_id = processor.Processor.ProcId;
@ -236,18 +244,21 @@ acpi_cpu_attach(device_t dev)
p_blk_length = processor.Processor.PblkLength; p_blk_length = processor.Processor.PblkLength;
/* allocate bus space if possible */ /* allocate bus space if possible */
if ((p_blk > 0) && (p_blk_length == 6)) { if (p_blk > 0 && p_blk_length == 6) {
rid = 0; rid = 0;
bus_set_resource(sc->cpu_dev, SYS_RES_IOPORT, rid, p_blk, p_blk_length); bus_set_resource(sc->cpu_dev, SYS_RES_IOPORT, rid, p_blk,
sc->cpu_p_blk = bus_alloc_resource(sc->cpu_dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, p_blk_length);
RF_ACTIVE); sc->cpu_p_blk = bus_alloc_resource(sc->cpu_dev, SYS_RES_IOPORT,
&rid, 0, ~0, 1, RF_ACTIVE);
ACPI_DEBUG_PRINT((ACPI_DB_IO, "acpi_cpu%d: throttling with P_BLK at 0x%x/%d%s\n", ACPI_DEBUG_PRINT((ACPI_DB_IO, "acpi_cpu%d: throttling with P_BLK "
device_get_unit(sc->cpu_dev), p_blk, p_blk_length, "at 0x%x/%d%s\n", device_get_unit(sc->cpu_dev),
sc->cpu_p_blk ? "" : " (shadowed)")); p_blk, p_blk_length,
sc->cpu_p_blk ? "" : " (shadowed)"));
} }
} }
return_VALUE(0);
return_VALUE (0);
} }
/* /*
@ -264,36 +275,42 @@ acpi_cpu_init_throttling(void *arg)
ACPI_LOCK; ACPI_LOCK;
/* get set of CPU devices */ /* Get set of CPU devices */
devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices); devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices);
/* initialise throttling states */ /* Initialise throttling states */
cpu_max_state = CPU_MAX_SPEED; cpu_max_state = CPU_MAX_SPEED;
cpu_performance_state = cpu_max_state; cpu_performance_state = cpu_max_state;
cpu_economy_state = cpu_performance_state / 2; cpu_economy_state = cpu_performance_state / 2;
if (cpu_economy_state == 0) /* 0 is 'reserved' */
/* 0 is 'reserved' */
if (cpu_economy_state == 0)
cpu_economy_state++; cpu_economy_state++;
if (TUNABLE_INT_FETCH("hw.acpi.cpu.performance_speed", if (TUNABLE_INT_FETCH("hw.acpi.cpu.performance_speed", &cpu_temp_speed) &&
&cpu_temp_speed) && cpu_temp_speed > 0 && cpu_temp_speed > 0 && cpu_temp_speed <= cpu_max_state) {
cpu_temp_speed <= cpu_max_state)
cpu_performance_state = cpu_temp_speed; cpu_performance_state = cpu_temp_speed;
if (TUNABLE_INT_FETCH("hw.acpi.cpu.economy_speed",
&cpu_temp_speed) && cpu_temp_speed > 0 &&
cpu_temp_speed <= cpu_max_state)
cpu_economy_state = cpu_temp_speed;
/* register performance profile change handler */
EVENTHANDLER_REGISTER(power_profile_change, acpi_cpu_power_profile, NULL, 0);
/* if ACPI 2.0+, signal platform that we are taking over throttling */
if (cpu_pstate_cnt != 0) {
/* XXX should be a generic interface for this */
AcpiOsWritePort(cpu_smi_cmd, cpu_pstate_cnt, 8);
} }
if (TUNABLE_INT_FETCH("hw.acpi.cpu.economy_speed", &cpu_temp_speed) &&
cpu_temp_speed > 0 && cpu_temp_speed <= cpu_max_state) {
cpu_economy_state = cpu_temp_speed;
}
/* Register performance profile change handler */
EVENTHANDLER_REGISTER(power_profile_change, acpi_cpu_power_profile, NULL,
0);
/*
* If ACPI 2.0+, signal platform that we are taking over throttling
* XXX should be a generic interface for this
*/
if (cpu_pstate_cnt != 0)
AcpiOsWritePort(cpu_smi_cmd, cpu_pstate_cnt, 8);
ACPI_UNLOCK; ACPI_UNLOCK;
/* set initial speed */ /* Set initial speed */
acpi_cpu_power_profile(NULL); acpi_cpu_power_profile(NULL);
printf("acpi_cpu: throttling enabled, %d steps (100%% to %d.%d%%), " printf("acpi_cpu: throttling enabled, %d steps (100%% to %d.%d%%), "
@ -315,32 +332,31 @@ acpi_cpu_set_speed(u_int32_t speed)
ACPI_ASSERTLOCK; ACPI_ASSERTLOCK;
/* iterate over processors */ /* Iterate over processors */
for (i = 0; i < cpu_ndevices; i++) { for (i = 0; i < cpu_ndevices; i++) {
sc = device_get_softc(cpu_devices[i]); sc = device_get_softc(cpu_devices[i]);
if (sc->cpu_p_blk == NULL) if (sc->cpu_p_blk == NULL)
continue; continue;
/* get the current P_CNT value and disable throttling */ /* Get the current P_CNT value and disable throttling */
p_cnt = CPU_GET_P_CNT(sc); p_cnt = CPU_GET_P_CNT(sc);
p_cnt &= ~CPU_P_CNT_THT_EN; p_cnt &= ~CPU_P_CNT_THT_EN;
CPU_SET_P_CNT(sc, p_cnt); CPU_SET_P_CNT(sc, p_cnt);
/* if we're at maximum speed, that's all */ /* If we're at maximum speed, that's all */
if (speed < CPU_MAX_SPEED) { if (speed < CPU_MAX_SPEED) {
/* Mask the old CLK_VAL off and or-in the new value */
/* mask the old CLK_VAL off and or-in the new value */
clk_val = CPU_MAX_SPEED << cpu_duty_offset; clk_val = CPU_MAX_SPEED << cpu_duty_offset;
p_cnt &= ~clk_val; p_cnt &= ~clk_val;
p_cnt |= (speed << cpu_duty_offset); p_cnt |= (speed << cpu_duty_offset);
/* write the new P_CNT value and then enable throttling */ /* Write the new P_CNT value and then enable throttling */
CPU_SET_P_CNT(sc, p_cnt); CPU_SET_P_CNT(sc, p_cnt);
p_cnt |= CPU_P_CNT_THT_EN; p_cnt |= CPU_P_CNT_THT_EN;
CPU_SET_P_CNT(sc, p_cnt); CPU_SET_P_CNT(sc, p_cnt);
} }
ACPI_VPRINT(sc->cpu_dev, acpi_device_get_parent_softc(sc->cpu_dev), ACPI_VPRINT(sc->cpu_dev, acpi_device_get_parent_softc(sc->cpu_dev),
"set speed to %d.%d%%\n", CPU_SPEED_PRINTABLE(speed)); "set speed to %d.%d%%\n", CPU_SPEED_PRINTABLE(speed));
} }
cpu_current_state = speed; cpu_current_state = speed;
} }
@ -358,10 +374,8 @@ acpi_cpu_power_profile(void *arg)
ACPI_LOCK_DECL; ACPI_LOCK_DECL;
state = power_profile_get_state(); state = power_profile_get_state();
if (state != POWER_PROFILE_PERFORMANCE && if (state != POWER_PROFILE_PERFORMANCE && state != POWER_PROFILE_ECONOMY)
state != POWER_PROFILE_ECONOMY) {
return; return;
}
ACPI_LOCK; ACPI_LOCK;
@ -400,17 +414,15 @@ acpi_cpu_speed_sysctl(SYSCTL_HANDLER_ARGS)
arg = *argp; arg = *argp;
error = sysctl_handle_int(oidp, &arg, 0, req); error = sysctl_handle_int(oidp, &arg, 0, req);
/* error or no new value */ /* Error or no new value */
if ((error != 0) || (req->newptr == NULL)) if (error != 0 || req->newptr == NULL)
return(error); return (error);
if (arg < 1 || arg > cpu_max_state)
/* range check */ return (EINVAL);
if ((arg < 1) || (arg > cpu_max_state))
return(EINVAL);
/* set new value and possibly switch */ /* Set new value and possibly switch */
*argp = arg; *argp = arg;
acpi_cpu_power_profile(NULL); acpi_cpu_power_profile(NULL);
return(0); return (0);
} }

View File

@ -37,12 +37,9 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h> #include <sys/proc.h>
#include "acpi.h" #include "acpi.h"
#include <dev/acpica/acpivar.h> #include <dev/acpica/acpivar.h>
/* /* Hooks for the ACPI CA debugging infrastructure */
* Hooks for the ACPI CA debugging infrastructure
*/
#define _COMPONENT ACPI_BUTTON #define _COMPONENT ACPI_BUTTON
ACPI_MODULE_NAME("LID") ACPI_MODULE_NAME("LID")
@ -81,13 +78,13 @@ DRIVER_MODULE(acpi_lid, acpi, acpi_lid_driver, acpi_lid_devclass, 0, 0);
static int static int
acpi_lid_probe(device_t dev) acpi_lid_probe(device_t dev)
{ {
if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) && if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("lid") &&
!acpi_disabled("lid") &&
acpi_MatchHid(dev, "PNP0C0D")) { acpi_MatchHid(dev, "PNP0C0D")) {
device_set_desc(dev, "Control Method Lid Switch"); device_set_desc(dev, "Control Method Lid Switch");
return(0); return (0);
} }
return(ENXIO); return (ENXIO);
} }
static int static int
@ -101,12 +98,12 @@ acpi_lid_attach(device_t dev)
sc->lid_dev = dev; sc->lid_dev = dev;
sc->lid_handle = acpi_get_handle(dev); sc->lid_handle = acpi_get_handle(dev);
/* /* Install notification handler */
* Install notification handler AcpiInstallNotifyHandler(sc->lid_handle, ACPI_DEVICE_NOTIFY,
*/ acpi_lid_notify_handler, sc);
AcpiInstallNotifyHandler(sc->lid_handle, ACPI_DEVICE_NOTIFY, acpi_lid_notify_handler, sc);
acpi_device_enable_wake_capability(sc->lid_handle, 1); acpi_device_enable_wake_capability(sc->lid_handle, 1);
return_VALUE(0);
return_VALUE (0);
} }
static int static int
@ -130,6 +127,7 @@ acpi_lid_notify_status_changed(void *arg)
{ {
struct acpi_lid_softc *sc; struct acpi_lid_softc *sc;
struct acpi_softc *acpi_sc; struct acpi_softc *acpi_sc;
ACPI_STATUS status;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@ -140,22 +138,21 @@ acpi_lid_notify_status_changed(void *arg)
* Zero: The lid is closed * Zero: The lid is closed
* Non-zero: The lid is open * Non-zero: The lid is open
*/ */
if (ACPI_FAILURE(acpi_EvaluateInteger(sc->lid_handle, "_LID", &sc->lid_status))) status = acpi_EvaluateInteger(sc->lid_handle, "_LID", &sc->lid_status);
if (ACPI_FAILURE(status))
return_VOID; return_VOID;
acpi_sc = acpi_device_get_parent_softc(sc->lid_dev); acpi_sc = acpi_device_get_parent_softc(sc->lid_dev);
if (acpi_sc == NULL) { if (acpi_sc == NULL)
return_VOID; return_VOID;
}
ACPI_VPRINT(sc->lid_dev, acpi_sc, ACPI_VPRINT(sc->lid_dev, acpi_sc, "Lid %s\n",
"Lid %s\n", sc->lid_status ? "opened" : "closed"); sc->lid_status ? "opened" : "closed");
if (sc->lid_status == 0) { if (sc->lid_status == 0)
EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_sx); EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_sx);
} else { else
EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_sx); EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_sx);
}
return_VOID; return_VOID;
} }
@ -172,11 +169,13 @@ acpi_lid_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
switch (notify) { switch (notify) {
case ACPI_NOTIFY_STATUS_CHANGED: case ACPI_NOTIFY_STATUS_CHANGED:
AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_lid_notify_status_changed, sc); AcpiOsQueueForExecution(OSD_PRIORITY_LO,
acpi_lid_notify_status_changed, sc);
break; break;
default: default:
break; /* unknown notification value */ break;
} }
return_VOID; return_VOID;
} }

View File

@ -27,27 +27,14 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include "opt_acpi.h" /* XXX trim includes */ #include "opt_acpi.h"
#include <sys/param.h> #include <sys/param.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/bus.h> #include <sys/bus.h>
#include <sys/conf.h>
#include <sys/ioccom.h>
#include <sys/reboot.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/ctype.h>
#include <machine/clock.h>
#include <machine/resource.h>
#include "acpi.h" #include "acpi.h"
#include <dev/acpica/acpivar.h> #include <dev/acpica/acpivar.h>
#include <dev/acpica/acpiio.h>
/* /*
* ACPI power resource management. * ACPI power resource management.
@ -70,62 +57,58 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_ACPIPWR, "acpipwr", "ACPI power resources"); MALLOC_DEFINE(M_ACPIPWR, "acpipwr", "ACPI power resources");
/* /* Hooks for the ACPI CA debugging infrastructure */
* Hooks for the ACPI CA debugging infrastructure
*/
#define _COMPONENT ACPI_POWER #define _COMPONENT ACPI_POWER
ACPI_MODULE_NAME("POWERRES") ACPI_MODULE_NAME("POWERRES")
/* return values from _STA on a power resource */ /* Return values from _STA on a power resource */
#define ACPI_PWR_OFF 0 #define ACPI_PWR_OFF 0
#define ACPI_PWR_ON 1 #define ACPI_PWR_ON 1
/* /* A relationship between a power resource and a consumer. */
* A relationship between a power resource and a consumer.
*/
struct acpi_powerreference { struct acpi_powerreference {
struct acpi_powerconsumer *ar_consumer; struct acpi_powerconsumer *ar_consumer;
struct acpi_powerresource *ar_resource; struct acpi_powerresource *ar_resource;
TAILQ_ENTRY(acpi_powerreference) ar_rlink; /* link on resource list */ TAILQ_ENTRY(acpi_powerreference) ar_rlink; /* link on resource list */
TAILQ_ENTRY(acpi_powerreference) ar_clink; /* link on consumer */ TAILQ_ENTRY(acpi_powerreference) ar_clink; /* link on consumer */
}; };
/* /* A power-managed device. */
* A power-managed device.
*/
struct acpi_powerconsumer { struct acpi_powerconsumer {
ACPI_HANDLE ac_consumer; /* device which is powered */ /* Device which is powered */
int ac_state; ACPI_HANDLE ac_consumer;
TAILQ_ENTRY(acpi_powerconsumer) ac_link; int ac_state;
TAILQ_HEAD(,acpi_powerreference) ac_references; TAILQ_ENTRY(acpi_powerconsumer) ac_link;
TAILQ_HEAD(,acpi_powerreference) ac_references;
}; };
/* /* A power resource. */
* A power resource.
*/
struct acpi_powerresource { struct acpi_powerresource {
TAILQ_ENTRY(acpi_powerresource) ap_link; TAILQ_ENTRY(acpi_powerresource) ap_link;
TAILQ_HEAD(,acpi_powerreference) ap_references; TAILQ_HEAD(,acpi_powerreference) ap_references;
ACPI_HANDLE ap_resource; /* the resource's handle */ ACPI_HANDLE ap_resource;
ACPI_INTEGER ap_systemlevel; ACPI_INTEGER ap_systemlevel;
ACPI_INTEGER ap_order; ACPI_INTEGER ap_order;
}; };
static TAILQ_HEAD(acpi_powerresource_list, acpi_powerresource) acpi_powerresources; static TAILQ_HEAD(acpi_powerresource_list, acpi_powerresource)
static TAILQ_HEAD(acpi_powerconsumer_list, acpi_powerconsumer) acpi_powerconsumers; acpi_powerresources;
static TAILQ_HEAD(acpi_powerconsumer_list, acpi_powerconsumer)
acpi_powerconsumers;
static ACPI_STATUS acpi_pwr_register_consumer(ACPI_HANDLE consumer); static ACPI_STATUS acpi_pwr_register_consumer(ACPI_HANDLE consumer);
static ACPI_STATUS acpi_pwr_deregister_consumer(ACPI_HANDLE consumer); static ACPI_STATUS acpi_pwr_deregister_consumer(ACPI_HANDLE consumer);
static ACPI_STATUS acpi_pwr_register_resource(ACPI_HANDLE res); static ACPI_STATUS acpi_pwr_register_resource(ACPI_HANDLE res);
static ACPI_STATUS acpi_pwr_deregister_resource(ACPI_HANDLE res); static ACPI_STATUS acpi_pwr_deregister_resource(ACPI_HANDLE res);
static void acpi_pwr_reference_resource(ACPI_OBJECT *obj, void *arg); static void acpi_pwr_reference_resource(ACPI_OBJECT *obj,
static ACPI_STATUS acpi_pwr_switch_power(void); void *arg);
static struct acpi_powerresource *acpi_pwr_find_resource(ACPI_HANDLE res); static ACPI_STATUS acpi_pwr_switch_power(void);
static struct acpi_powerconsumer *acpi_pwr_find_consumer(ACPI_HANDLE consumer); static struct acpi_powerresource
*acpi_pwr_find_resource(ACPI_HANDLE res);
static struct acpi_powerconsumer
*acpi_pwr_find_consumer(ACPI_HANDLE consumer);
/* /* Initialise our lists. */
* Initialise our lists.
*/
static void static void
acpi_pwr_init(void *junk) acpi_pwr_init(void *junk)
{ {
@ -152,11 +135,11 @@ acpi_pwr_register_resource(ACPI_HANDLE res)
rp = NULL; rp = NULL;
buf.Pointer = NULL; buf.Pointer = NULL;
/* look to see if we know about this resource */ /* Look to see if we know about this resource */
if (acpi_pwr_find_resource(res) != NULL) if (acpi_pwr_find_resource(res) != NULL)
return_ACPI_STATUS(AE_OK); /* already know about it */ return_ACPI_STATUS (AE_OK); /* already know about it */
/* allocate a new resource */ /* Allocate a new resource */
if ((rp = malloc(sizeof(*rp), M_ACPIPWR, M_NOWAIT | M_ZERO)) == NULL) { if ((rp = malloc(sizeof(*rp), M_ACPIPWR, M_NOWAIT | M_ZERO)) == NULL) {
status = AE_NO_MEMORY; status = AE_NO_MEMORY;
goto out; goto out;
@ -164,7 +147,7 @@ acpi_pwr_register_resource(ACPI_HANDLE res)
TAILQ_INIT(&rp->ap_references); TAILQ_INIT(&rp->ap_references);
rp->ap_resource = res; rp->ap_resource = res;
/* get the Power Resource object */ /* Get the Power Resource object */
buf.Length = ACPI_ALLOCATE_BUFFER; buf.Length = ACPI_ALLOCATE_BUFFER;
if (ACPI_FAILURE(status = AcpiEvaluateObject(res, NULL, NULL, &buf))) { if (ACPI_FAILURE(status = AcpiEvaluateObject(res, NULL, NULL, &buf))) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "no power resource object\n")); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "no power resource object\n"));
@ -172,35 +155,40 @@ acpi_pwr_register_resource(ACPI_HANDLE res)
} }
obj = buf.Pointer; obj = buf.Pointer;
if (obj->Type != ACPI_TYPE_POWER) { if (obj->Type != ACPI_TYPE_POWER) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "questionable power resource object %s\n", acpi_name(res))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"questionable power resource object %s\n",
acpi_name(res)));
status = AE_TYPE; status = AE_TYPE;
goto out; goto out;
} }
rp->ap_systemlevel = obj->PowerResource.SystemLevel; rp->ap_systemlevel = obj->PowerResource.SystemLevel;
rp->ap_order = obj->PowerResource.ResourceOrder; rp->ap_order = obj->PowerResource.ResourceOrder;
/* sort the resource into the list */ /* Sort the resource into the list */
status = AE_OK; status = AE_OK;
srp = TAILQ_FIRST(&acpi_powerresources); srp = TAILQ_FIRST(&acpi_powerresources);
if ((srp == NULL) || (rp->ap_order < srp->ap_order)) { if (srp == NULL || rp->ap_order < srp->ap_order) {
TAILQ_INSERT_HEAD(&acpi_powerresources, rp, ap_link); TAILQ_INSERT_HEAD(&acpi_powerresources, rp, ap_link);
goto done; goto done;
} }
TAILQ_FOREACH(srp, &acpi_powerresources, ap_link) TAILQ_FOREACH(srp, &acpi_powerresources, ap_link) {
if (rp->ap_order < srp->ap_order) { if (rp->ap_order < srp->ap_order) {
TAILQ_INSERT_BEFORE(srp, rp, ap_link); TAILQ_INSERT_BEFORE(srp, rp, ap_link);
goto done; goto done;
} }
}
TAILQ_INSERT_TAIL(&acpi_powerresources, rp, ap_link); TAILQ_INSERT_TAIL(&acpi_powerresources, rp, ap_link);
done: done:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "registered power resource %s\n", acpi_name(res))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"registered power resource %s\n", acpi_name(res)));
out: out:
if (buf.Pointer != NULL) if (buf.Pointer != NULL)
AcpiOsFree(buf.Pointer); AcpiOsFree(buf.Pointer);
if (ACPI_FAILURE(status) && (rp != NULL)) if (ACPI_FAILURE(status) && rp != NULL)
free(rp, M_ACPIPWR); free(rp, M_ACPIPWR);
return_ACPI_STATUS(status); return_ACPI_STATUS (status);
} }
/* /*
@ -215,21 +203,22 @@ acpi_pwr_deregister_resource(ACPI_HANDLE res)
rp = NULL; rp = NULL;
/* find the resource */ /* Find the resource */
if ((rp = acpi_pwr_find_resource(res)) == NULL) if ((rp = acpi_pwr_find_resource(res)) == NULL)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
/* check that there are no consumers referencing this resource */ /* Check that there are no consumers referencing this resource */
if (TAILQ_FIRST(&rp->ap_references) != NULL) if (TAILQ_FIRST(&rp->ap_references) != NULL)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
/* pull it off the list and free it */ /* Pull it off the list and free it */
TAILQ_REMOVE(&acpi_powerresources, rp, ap_link); TAILQ_REMOVE(&acpi_powerresources, rp, ap_link);
free(rp, M_ACPIPWR); free(rp, M_ACPIPWR);
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "deregistered power resource %s\n", acpi_name(res))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "deregistered power resource %s\n",
acpi_name(res)));
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
} }
/* /*
@ -244,22 +233,24 @@ acpi_pwr_register_consumer(ACPI_HANDLE consumer)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
/* check to see whether we know about this consumer already */ /* Check to see whether we know about this consumer already */
if ((pc = acpi_pwr_find_consumer(consumer)) != NULL) if ((pc = acpi_pwr_find_consumer(consumer)) != NULL)
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
/* allocate a new power consumer */ /* Allocate a new power consumer */
if ((pc = malloc(sizeof(*pc), M_ACPIPWR, M_NOWAIT)) == NULL) if ((pc = malloc(sizeof(*pc), M_ACPIPWR, M_NOWAIT)) == NULL)
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS (AE_NO_MEMORY);
TAILQ_INSERT_HEAD(&acpi_powerconsumers, pc, ac_link); TAILQ_INSERT_HEAD(&acpi_powerconsumers, pc, ac_link);
TAILQ_INIT(&pc->ac_references); TAILQ_INIT(&pc->ac_references);
pc->ac_consumer = consumer; pc->ac_consumer = consumer;
pc->ac_state = ACPI_STATE_UNKNOWN; /* XXX we should try to find its current state */ /* XXX we should try to find its current state */
pc->ac_state = ACPI_STATE_UNKNOWN;
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "registered power consumer %s\n", acpi_name(consumer))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "registered power consumer %s\n",
acpi_name(consumer)));
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
} }
/* /*
@ -275,20 +266,21 @@ acpi_pwr_deregister_consumer(ACPI_HANDLE consumer)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
/* find the consumer */ /* Find the consumer */
if ((pc = acpi_pwr_find_consumer(consumer)) == NULL) if ((pc = acpi_pwr_find_consumer(consumer)) == NULL)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
/* make sure the consumer's not referencing anything right now */ /* Make sure the consumer's not referencing anything right now */
if (TAILQ_FIRST(&pc->ac_references) != NULL) if (TAILQ_FIRST(&pc->ac_references) != NULL)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
/* pull the consumer off the list and free it */ /* Pull the consumer off the list and free it */
TAILQ_REMOVE(&acpi_powerconsumers, pc, ac_link); TAILQ_REMOVE(&acpi_powerconsumers, pc, ac_link);
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "deregistered power consumer %s\n", acpi_name(consumer))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "deregistered power consumer %s\n",
acpi_name(consumer)));
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
} }
/* /*
@ -308,20 +300,20 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
/* find the consumer */ /* Find the consumer */
if ((pc = acpi_pwr_find_consumer(consumer)) == NULL) { if ((pc = acpi_pwr_find_consumer(consumer)) == NULL) {
if (ACPI_FAILURE(status = acpi_pwr_register_consumer(consumer))) if (ACPI_FAILURE(status = acpi_pwr_register_consumer(consumer)))
return_ACPI_STATUS(status); return_ACPI_STATUS (status);
if ((pc = acpi_pwr_find_consumer(consumer)) == NULL) { if ((pc = acpi_pwr_find_consumer(consumer)) == NULL) {
return_ACPI_STATUS(AE_ERROR); /* something very wrong */ return_ACPI_STATUS (AE_ERROR); /* something very wrong */
} }
} }
/* check for valid transitions */ /* Check for valid transitions */
if ((pc->ac_state == ACPI_STATE_D3) && (state != ACPI_STATE_D0)) if (pc->ac_state == ACPI_STATE_D3 && state != ACPI_STATE_D0)
return_ACPI_STATUS(AE_BAD_PARAMETER); /* can only go to D0 from D3 */ return_ACPI_STATUS (AE_BAD_PARAMETER); /* can only go to D0 from D3 */
/* find transition mechanism(s) */ /* Find transition mechanism(s) */
switch(state) { switch(state) {
case ACPI_STATE_D0: case ACPI_STATE_D0:
method_name = "_PS0"; method_name = "_PS0";
@ -340,10 +332,10 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
reslist_name = "_PR3"; reslist_name = "_PR3";
break; break;
default: default:
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
} }
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "setup to switch %s D%d -> D%d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "setup to switch %s D%d -> D%d\n",
acpi_name(consumer), pc->ac_state, state)); acpi_name(consumer), pc->ac_state, state));
/* /*
* Verify that this state is supported, ie. one of method or * Verify that this state is supported, ie. one of method or
@ -361,26 +353,25 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
method_handle = NULL; method_handle = NULL;
if (ACPI_FAILURE(AcpiGetHandle(consumer, reslist_name, &reslist_handle))) if (ACPI_FAILURE(AcpiGetHandle(consumer, reslist_name, &reslist_handle)))
reslist_handle = NULL; reslist_handle = NULL;
if ((reslist_handle == NULL) && (method_handle == NULL)) { if (reslist_handle == NULL && method_handle == NULL) {
if (state == ACPI_STATE_D0) { if (state == ACPI_STATE_D0) {
pc->ac_state = ACPI_STATE_D0; pc->ac_state = ACPI_STATE_D0;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
} }
if (state != ACPI_STATE_D3) { if (state != ACPI_STATE_D3)
goto bad; goto bad;
}
/* turn off the resources listed in _PR0 to go to D3. */ /* Turn off the resources listed in _PR0 to go to D3. */
if (ACPI_FAILURE(AcpiGetHandle(consumer, "_PR0", &pr0_handle))) { if (ACPI_FAILURE(AcpiGetHandle(consumer, "_PR0", &pr0_handle)))
goto bad; goto bad;
}
reslist_buffer.Length = ACPI_ALLOCATE_BUFFER; reslist_buffer.Length = ACPI_ALLOCATE_BUFFER;
if (ACPI_FAILURE(status = AcpiEvaluateObject(pr0_handle, NULL, NULL, &reslist_buffer))) { status = AcpiEvaluateObject(pr0_handle, NULL, NULL, &reslist_buffer);
if (ACPI_FAILURE(status))
goto bad; goto bad;
}
reslist_object = (ACPI_OBJECT *)reslist_buffer.Pointer; reslist_object = (ACPI_OBJECT *)reslist_buffer.Pointer;
if ((reslist_object->Type != ACPI_TYPE_PACKAGE) || if (reslist_object->Type != ACPI_TYPE_PACKAGE ||
(reslist_object->Package.Count == 0)) { reslist_object->Package.Count == 0) {
goto bad; goto bad;
} }
AcpiOsFree(reslist_buffer.Pointer); AcpiOsFree(reslist_buffer.Pointer);
@ -393,27 +384,33 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
*/ */
if (reslist_handle != NULL) { if (reslist_handle != NULL) {
reslist_buffer.Length = ACPI_ALLOCATE_BUFFER; reslist_buffer.Length = ACPI_ALLOCATE_BUFFER;
if (ACPI_FAILURE(status = AcpiEvaluateObject(reslist_handle, NULL, NULL, &reslist_buffer))) { status = AcpiEvaluateObject(reslist_handle, NULL, NULL,
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't evaluate resource list %s\n", &reslist_buffer);
acpi_name(reslist_handle))); if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"can't evaluate resource list %s\n",
acpi_name(reslist_handle)));
goto out; goto out;
} }
reslist_object = (ACPI_OBJECT *)reslist_buffer.Pointer; reslist_object = (ACPI_OBJECT *)reslist_buffer.Pointer;
if (reslist_object->Type != ACPI_TYPE_PACKAGE) { if (reslist_object->Type != ACPI_TYPE_PACKAGE) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "resource list is not ACPI_TYPE_PACKAGE (%d)\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
reslist_object->Type)); "resource list is not ACPI_TYPE_PACKAGE (%d)\n",
reslist_object->Type));
status = AE_TYPE; status = AE_TYPE;
goto out; goto out;
} }
} }
/* /*
* Now we are ready to switch, so kill off any current power resource references. * Now we are ready to switch, so kill off any current power
* resource references.
*/ */
res_changed = 0; res_changed = 0;
while((pr = TAILQ_FIRST(&pc->ac_references)) != NULL) { while((pr = TAILQ_FIRST(&pc->ac_references)) != NULL) {
res_changed = 1; res_changed = 1;
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "removing reference to %s\n", acpi_name(pr->ar_resource->ap_resource))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "removing reference to %s\n",
acpi_name(pr->ar_resource->ap_resource)));
TAILQ_REMOVE(&pr->ar_resource->ap_references, pr, ar_rlink); TAILQ_REMOVE(&pr->ar_resource->ap_references, pr, ar_rlink);
TAILQ_REMOVE(&pc->ac_references, pr, ar_clink); TAILQ_REMOVE(&pc->ac_references, pr, ar_clink);
free(pr, M_ACPIPWR); free(pr, M_ACPIPWR);
@ -427,7 +424,8 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
if (reslist_object != NULL) { if (reslist_object != NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "referencing %d new resources\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "referencing %d new resources\n",
reslist_object->Package.Count)); reslist_object->Package.Count));
acpi_ForeachPackageObject(reslist_object, acpi_pwr_reference_resource, pc); acpi_ForeachPackageObject(reslist_object, acpi_pwr_reference_resource,
pc);
res_changed = 1; res_changed = 1;
} }
@ -436,36 +434,43 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
* pass now. * pass now.
*/ */
if (ACPI_FAILURE(status = acpi_pwr_switch_power())) { if (ACPI_FAILURE(status = acpi_pwr_switch_power())) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "failed to correctly switch resources to move %s to D%d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"failed to switch resources from %s to D%d\n",
acpi_name(consumer), state)); acpi_name(consumer), state));
goto out; /* XXX is this appropriate? Should we return to previous state? */
/* XXX is this appropriate? Should we return to previous state? */
goto out;
} }
/* invoke power state switch method (if present) */ /* Invoke power state switch method (if present) */
if (method_handle != NULL) { if (method_handle != NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "invoking state transition method %s\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
acpi_name(method_handle))); "invoking state transition method %s\n",
if (ACPI_FAILURE(status = AcpiEvaluateObject(method_handle, NULL, NULL, NULL))) { acpi_name(method_handle)));
status = AcpiEvaluateObject(method_handle, NULL, NULL, NULL);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "failed to set state - %s\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "failed to set state - %s\n",
AcpiFormatException(status))); AcpiFormatException(status)));
pc->ac_state = ACPI_STATE_UNKNOWN; pc->ac_state = ACPI_STATE_UNKNOWN;
goto out; /* XXX Should we return to previous state? */
/* XXX Should we return to previous state? */
goto out;
} }
} }
/* transition was successful */ /* Transition was successful */
pc->ac_state = state; pc->ac_state = state;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
bad: bad:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "attempt to set unsupported state D%d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
state)); "attempt to set unsupported state D%d\n", state));
status = AE_BAD_PARAMETER; status = AE_BAD_PARAMETER;
out: out:
if (reslist_buffer.Pointer != NULL) if (reslist_buffer.Pointer != NULL)
AcpiOsFree(reslist_buffer.Pointer); AcpiOsFree(reslist_buffer.Pointer);
return_ACPI_STATUS(status); return_ACPI_STATUS (status);
} }
/* /*
@ -487,44 +492,48 @@ acpi_pwr_reference_resource(ACPI_OBJECT *obj, void *arg)
switch (obj->Type) { switch (obj->Type) {
case ACPI_TYPE_ANY: case ACPI_TYPE_ANY:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "building reference from %s to %s\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "building reference from %s to %s\n",
acpi_name(pc->ac_consumer), acpi_name(obj->Reference.Handle))); acpi_name(pc->ac_consumer),
acpi_name(obj->Reference.Handle)));
res = obj->Reference.Handle; res = obj->Reference.Handle;
break; break;
case ACPI_TYPE_STRING: case ACPI_TYPE_STRING:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "building reference from %s to %s\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "building reference from %s to %s\n",
acpi_name(pc->ac_consumer), obj->String.Pointer)); acpi_name(pc->ac_consumer), obj->String.Pointer));
/* get the handle of the resource */ /* Get the handle of the resource */
if (ACPI_FAILURE(status = AcpiGetHandle(NULL, obj->String.Pointer, &res))) { status = AcpiGetHandle(NULL, obj->String.Pointer, &res);
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "couldn't find power resource %s\n", if (ACPI_FAILURE(status)) {
obj->String.Pointer)); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"couldn't find power resource %s\n",
obj->String.Pointer));
return_VOID; return_VOID;
} }
break; break;
default: default:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "don't know how to create a power reference to object type %d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
obj->Type)); "can't create a power reference for object type %d\n",
obj->Type));
return_VOID; return_VOID;
} }
/* create/look up the resource */ /* Create/look up the resource */
if (ACPI_FAILURE(status = acpi_pwr_register_resource(res))) { if (ACPI_FAILURE(status = acpi_pwr_register_resource(res))) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "couldn't register power resource %s - %s\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
obj->String.Pointer, AcpiFormatException(status))); "couldn't register power resource %s - %s\n",
obj->String.Pointer, AcpiFormatException(status)));
return_VOID; return_VOID;
} }
if ((rp = acpi_pwr_find_resource(res)) == NULL) { if ((rp = acpi_pwr_find_resource(res)) == NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "power resource list corrupted\n")); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "power resource list corrupted\n"));
return_VOID; return_VOID;
} }
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "found power resource %s\n", acpi_name(rp->ap_resource))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "found power resource %s\n",
acpi_name(rp->ap_resource)));
/* create a reference between the consumer and resource */ /* Create a reference between the consumer and resource */
if ((pr = malloc(sizeof(*pr), M_ACPIPWR, M_NOWAIT | M_ZERO)) == NULL) { if ((pr = malloc(sizeof(*pr), M_ACPIPWR, M_NOWAIT | M_ZERO)) == NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "couldn't allocate memory for a power consumer reference\n")); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"allocation failed for a power consumer reference\n"));
return_VOID; return_VOID;
} }
pr->ar_consumer = pc; pr->ar_consumer = pc;
@ -556,16 +565,20 @@ acpi_pwr_switch_power(void)
*/ */
TAILQ_FOREACH(rp, &acpi_powerresources, ap_link) { TAILQ_FOREACH(rp, &acpi_powerresources, ap_link) {
if (TAILQ_FIRST(&rp->ap_references) == NULL) { if (TAILQ_FIRST(&rp->ap_references) == NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "%s has no references, not turning on\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
acpi_name(rp->ap_resource))); "%s has no references, not turning on\n",
acpi_name(rp->ap_resource)));
continue; continue;
} }
/* we could cache this if we trusted it not to change under us */ /* We could cache this if we trusted it not to change under us */
if (ACPI_FAILURE(status = acpi_EvaluateInteger(rp->ap_resource, "_STA", &cur))) { status = acpi_EvaluateInteger(rp->ap_resource, "_STA", &cur);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get status of %s - %d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get status of %s - %d\n",
acpi_name(rp->ap_resource), status)); acpi_name(rp->ap_resource), status));
continue; /* XXX is this correct? Always switch if in doubt? */
/* XXX is this correct? Always switch if in doubt? */
continue;
} }
/* /*
@ -574,32 +587,40 @@ acpi_pwr_switch_power(void)
* help much. * help much.
*/ */
if (cur != ACPI_PWR_ON) { if (cur != ACPI_PWR_ON) {
if (ACPI_FAILURE(status = AcpiEvaluateObject(rp->ap_resource, "_ON", NULL, NULL))) { status = AcpiEvaluateObject(rp->ap_resource, "_ON", NULL, NULL);
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "failed to switch %s on - %s\n", if (ACPI_FAILURE(status)) {
acpi_name(rp->ap_resource), AcpiFormatException(status))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"failed to switch %s on - %s\n",
acpi_name(rp->ap_resource),
AcpiFormatException(status)));
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "switched %s on\n", acpi_name(rp->ap_resource))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "switched %s on\n",
acpi_name(rp->ap_resource)));
} }
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "%s is already on\n", acpi_name(rp->ap_resource))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "%s is already on\n",
acpi_name(rp->ap_resource)));
} }
} }
/* /* Sweep the list backwards turning things off. */
* Sweep the list backwards turning things off. TAILQ_FOREACH_REVERSE(rp, &acpi_powerresources, acpi_powerresource_list,
*/ ap_link) {
TAILQ_FOREACH_REVERSE(rp, &acpi_powerresources, acpi_powerresource_list, ap_link) {
if (TAILQ_FIRST(&rp->ap_references) != NULL) { if (TAILQ_FIRST(&rp->ap_references) != NULL) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "%s has references, not turning off\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
acpi_name(rp->ap_resource))); "%s has references, not turning off\n",
acpi_name(rp->ap_resource)));
continue; continue;
} }
/* we could cache this if we trusted it not to change under us */ /* We could cache this if we trusted it not to change under us */
if (ACPI_FAILURE(status = acpi_EvaluateInteger(rp->ap_resource, "_STA", &cur))) { status = acpi_EvaluateInteger(rp->ap_resource, "_STA", &cur);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get status of %s - %d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get status of %s - %d\n",
acpi_name(rp->ap_resource), status)); acpi_name(rp->ap_resource), status));
continue; /* XXX is this correct? Always switch if in doubt? */ /* XXX is this correct? Always switch if in doubt? */
continue;
} }
/* /*
@ -608,17 +629,23 @@ acpi_pwr_switch_power(void)
* help much. * help much.
*/ */
if (cur != ACPI_PWR_OFF) { if (cur != ACPI_PWR_OFF) {
if (ACPI_FAILURE(status = AcpiEvaluateObject(rp->ap_resource, "_OFF", NULL, NULL))) { status = AcpiEvaluateObject(rp->ap_resource, "_OFF", NULL, NULL);
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "failed to switch %s off - %s\n", if (ACPI_FAILURE(status)) {
acpi_name(rp->ap_resource), AcpiFormatException(status))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
"failed to switch %s off - %s\n",
acpi_name(rp->ap_resource),
AcpiFormatException(status)));
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "switched %s off\n", acpi_name(rp->ap_resource))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "switched %s off\n",
acpi_name(rp->ap_resource)));
} }
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "%s is already off\n", acpi_name(rp->ap_resource))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "%s is already off\n",
acpi_name(rp->ap_resource)));
} }
} }
return_ACPI_STATUS(AE_OK);
return_ACPI_STATUS (AE_OK);
} }
/* /*
@ -631,10 +658,12 @@ acpi_pwr_find_resource(ACPI_HANDLE res)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
TAILQ_FOREACH(rp, &acpi_powerresources, ap_link) TAILQ_FOREACH(rp, &acpi_powerresources, ap_link) {
if (rp->ap_resource == res) if (rp->ap_resource == res)
break; break;
return_PTR(rp); }
return_PTR (rp);
} }
/* /*
@ -647,9 +676,10 @@ acpi_pwr_find_consumer(ACPI_HANDLE consumer)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
TAILQ_FOREACH(pc, &acpi_powerconsumers, ac_link) TAILQ_FOREACH(pc, &acpi_powerconsumers, ac_link) {
if (pc->ac_consumer == consumer) if (pc->ac_consumer == consumer)
break; break;
return_PTR(pc); }
}
return_PTR (pc);
}

View File

@ -38,12 +38,9 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h> #include <sys/rman.h>
#include "acpi.h" #include "acpi.h"
#include <dev/acpica/acpivar.h> #include <dev/acpica/acpivar.h>
/* /* Hooks for the ACPI CA debugging infrastructure */
* Hooks for the ACPI CA debugging infrastructure
*/
#define _COMPONENT ACPI_BUS #define _COMPONENT ACPI_BUS
ACPI_MODULE_NAME("RESOURCE") ACPI_MODULE_NAME("RESOURCE")
@ -58,7 +55,8 @@ ACPI_MODULE_NAME("RESOURCE")
* code for _PRS someday. * code for _PRS someday.
*/ */
ACPI_STATUS ACPI_STATUS
acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set) acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
struct acpi_parse_resource_set *set)
{ {
ACPI_BUFFER buf; ACPI_BUFFER buf;
ACPI_RESOURCE *res; ACPI_RESOURCE *res;
@ -78,85 +76,79 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
* the PCI interrupt link. * the PCI interrupt link.
*/ */
/* /* Fetch the device's current resources. */
* Fetch the device's current resources.
*/
buf.Length = ACPI_ALLOCATE_BUFFER; buf.Length = ACPI_ALLOCATE_BUFFER;
if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) { if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
if (status != AE_NOT_FOUND) if (status != AE_NOT_FOUND)
printf("can't fetch resources for %s - %s\n", printf("can't fetch resources for %s - %s\n",
acpi_name(handle), AcpiFormatException(status)); acpi_name(handle), AcpiFormatException(status));
return_ACPI_STATUS(status); return_ACPI_STATUS (status);
} }
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
acpi_name(handle), (long)buf.Length)); acpi_name(handle), (long)buf.Length));
set->set_init(dev, &context); set->set_init(dev, &context);
/* /* Iterate through the resources */
* Iterate through the resources
*/
curr = buf.Pointer; curr = buf.Pointer;
last = (char *)buf.Pointer + buf.Length; last = (char *)buf.Pointer + buf.Length;
while (curr < last) { while (curr < last) {
res = (ACPI_RESOURCE *)curr; res = (ACPI_RESOURCE *)curr;
curr += res->Length; curr += res->Length;
/* /* Handle the individual resource types */
* Handle the individual resource types
*/
switch(res->Id) { switch(res->Id) {
case ACPI_RSTYPE_END_TAG: case ACPI_RSTYPE_END_TAG:
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
curr = last; curr = last;
break; break;
case ACPI_RSTYPE_FIXED_IO: case ACPI_RSTYPE_FIXED_IO:
if (res->Data.FixedIo.RangeLength <= 0) if (res->Data.FixedIo.RangeLength <= 0)
break; break;
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
res->Data.FixedIo.BaseAddress, res->Data.FixedIo.BaseAddress,
res->Data.FixedIo.RangeLength)); res->Data.FixedIo.RangeLength));
set->set_ioport(dev, context, set->set_ioport(dev, context,
res->Data.FixedIo.BaseAddress, res->Data.FixedIo.BaseAddress,
res->Data.FixedIo.RangeLength); res->Data.FixedIo.RangeLength);
break; break;
case ACPI_RSTYPE_IO: case ACPI_RSTYPE_IO:
if (res->Data.Io.RangeLength <= 0) if (res->Data.Io.RangeLength <= 0)
break; break;
if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) { if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
res->Data.Io.MinBaseAddress, res->Data.Io.MinBaseAddress,
res->Data.Io.RangeLength)); res->Data.Io.RangeLength));
set->set_ioport(dev, context, set->set_ioport(dev, context,
res->Data.Io.MinBaseAddress, res->Data.Io.MinBaseAddress,
res->Data.Io.RangeLength); res->Data.Io.RangeLength);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
res->Data.Io.MinBaseAddress, res->Data.Io.MinBaseAddress,
res->Data.Io.MaxBaseAddress, res->Data.Io.MaxBaseAddress,
res->Data.Io.RangeLength)); res->Data.Io.RangeLength));
set->set_iorange(dev, context, set->set_iorange(dev, context,
res->Data.Io.MinBaseAddress, res->Data.Io.MinBaseAddress,
res->Data.Io.MaxBaseAddress, res->Data.Io.MaxBaseAddress,
res->Data.Io.RangeLength, res->Data.Io.Alignment); res->Data.Io.RangeLength,
res->Data.Io.Alignment);
} }
break; break;
case ACPI_RSTYPE_FIXED_MEM32: case ACPI_RSTYPE_FIXED_MEM32:
if (res->Data.FixedMemory32.RangeLength <= 0) if (res->Data.FixedMemory32.RangeLength <= 0)
break; break;
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
res->Data.FixedMemory32.RangeBaseAddress, res->Data.FixedMemory32.RangeBaseAddress,
res->Data.FixedMemory32.RangeLength)); res->Data.FixedMemory32.RangeLength));
set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress, set->set_memory(dev, context,
res->Data.FixedMemory32.RangeBaseAddress,
res->Data.FixedMemory32.RangeLength); res->Data.FixedMemory32.RangeLength);
break; break;
case ACPI_RSTYPE_MEM32: case ACPI_RSTYPE_MEM32:
if (res->Data.Memory32.RangeLength <= 0) if (res->Data.Memory32.RangeLength <= 0)
break; break;
if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) { if (res->Data.Memory32.MinBaseAddress ==
res->Data.Memory32.MaxBaseAddress) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
res->Data.Memory32.MinBaseAddress, res->Data.Memory32.MinBaseAddress,
res->Data.Memory32.RangeLength)); res->Data.Memory32.RangeLength));
@ -165,9 +157,9 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
res->Data.Memory32.RangeLength); res->Data.Memory32.RangeLength);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
res->Data.Memory32.MinBaseAddress, res->Data.Memory32.MinBaseAddress,
res->Data.Memory32.MaxBaseAddress, res->Data.Memory32.MaxBaseAddress,
res->Data.Memory32.RangeLength)); res->Data.Memory32.RangeLength));
set->set_memoryrange(dev, context, set->set_memoryrange(dev, context,
res->Data.Memory32.MinBaseAddress, res->Data.Memory32.MinBaseAddress,
res->Data.Memory32.MaxBaseAddress, res->Data.Memory32.MaxBaseAddress,
@ -175,21 +167,22 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
res->Data.Memory32.Alignment); res->Data.Memory32.Alignment);
} }
break; break;
case ACPI_RSTYPE_MEM24: case ACPI_RSTYPE_MEM24:
if (res->Data.Memory24.RangeLength <= 0) if (res->Data.Memory24.RangeLength <= 0)
break; break;
if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) { if (res->Data.Memory24.MinBaseAddress ==
res->Data.Memory24.MaxBaseAddress) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
res->Data.Memory24.MinBaseAddress, res->Data.Memory24.MinBaseAddress,
res->Data.Memory24.RangeLength)); res->Data.Memory24.RangeLength));
set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress, set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
res->Data.Memory24.RangeLength); res->Data.Memory24.RangeLength);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
res->Data.Memory24.MinBaseAddress, res->Data.Memory24.MinBaseAddress,
res->Data.Memory24.MaxBaseAddress, res->Data.Memory24.MaxBaseAddress,
res->Data.Memory24.RangeLength)); res->Data.Memory24.RangeLength));
set->set_memoryrange(dev, context, set->set_memoryrange(dev, context,
res->Data.Memory24.MinBaseAddress, res->Data.Memory24.MinBaseAddress,
res->Data.Memory24.MaxBaseAddress, res->Data.Memory24.MaxBaseAddress,
@ -197,7 +190,6 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
res->Data.Memory24.Alignment); res->Data.Memory24.Alignment);
} }
break; break;
case ACPI_RSTYPE_IRQ: case ACPI_RSTYPE_IRQ:
/* /*
* from 1.0b 6.4.2 * from 1.0b 6.4.2
@ -207,78 +199,79 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
set->set_irq(dev, context, res->Data.Irq.Interrupts, set->set_irq(dev, context, res->Data.Irq.Interrupts,
res->Data.Irq.NumberOfInterrupts); res->Data.Irq.NumberOfInterrupts);
break; break;
case ACPI_RSTYPE_DMA: case ACPI_RSTYPE_DMA:
/* /*
* from 1.0b 6.4.3 * from 1.0b 6.4.3
* "This structure is repeated for each separate dma channel * "This structure is repeated for each separate dma channel
* required" * required"
*/ */
set->set_drq(dev, context, res->Data.Dma.Channels, set->set_drq(dev, context, res->Data.Dma.Channels,
res->Data.Dma.NumberOfChannels); res->Data.Dma.NumberOfChannels);
break; break;
case ACPI_RSTYPE_START_DPF: case ACPI_RSTYPE_START_DPF:
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n")); ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
set->set_start_dependant(dev, context, set->set_start_dependant(dev, context,
res->Data.StartDpf.CompatibilityPriority); res->Data.StartDpf.CompatibilityPriority);
break; break;
case ACPI_RSTYPE_END_DPF: case ACPI_RSTYPE_END_DPF:
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n")); ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
set->set_end_dependant(dev, context); set->set_end_dependant(dev, context);
break; break;
case ACPI_RSTYPE_ADDRESS32: case ACPI_RSTYPE_ADDRESS32:
if (res->Data.Address32.AddressLength <= 0) if (res->Data.Address32.AddressLength <= 0)
break; break;
if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) { if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
(res->Data.Address32.ResourceType == ACPI_IO_RANGE) ? "ignored Address32 %s producer\n",
"IO" : "Memory")); res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
"IO" : "Memory"));
break; break;
} }
if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE && if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
res->Data.Address32.ResourceType != ACPI_IO_RANGE) { res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
"ignored Address32 for non-memory, non-I/O\n")); "ignored Address32 for non-memory, non-I/O\n"));
break; break;
} }
if ((res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED) && if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
(res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)) { res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address32.MinAddressRange, "Address32/Memory 0x%x/%d\n",
res->Data.Address32.AddressLength)); res->Data.Address32.MinAddressRange,
res->Data.Address32.AddressLength));
set->set_memory(dev, context, set->set_memory(dev, context,
res->Data.Address32.MinAddressRange, res->Data.Address32.MinAddressRange,
res->Data.Address32.AddressLength); res->Data.Address32.AddressLength);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address32.MinAddressRange, "Address32/IO 0x%x/%d\n",
res->Data.Address32.AddressLength)); res->Data.Address32.MinAddressRange,
res->Data.Address32.AddressLength));
set->set_ioport(dev, context, set->set_ioport(dev, context,
res->Data.Address32.MinAddressRange, res->Data.Address32.MinAddressRange,
res->Data.Address32.AddressLength); res->Data.Address32.AddressLength);
} }
} else { } else {
if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address32.MinAddressRange, "Address32/Memory 0x%x-0x%x/%d\n",
res->Data.Address32.MaxAddressRange, res->Data.Address32.MinAddressRange,
res->Data.Address32.AddressLength)); res->Data.Address32.MaxAddressRange,
res->Data.Address32.AddressLength));
set->set_memoryrange(dev, context, set->set_memoryrange(dev, context,
res->Data.Address32.MinAddressRange, res->Data.Address32.MinAddressRange,
res->Data.Address32.MaxAddressRange, res->Data.Address32.MaxAddressRange,
res->Data.Address32.AddressLength, res->Data.Address32.AddressLength,
res->Data.Address32.Granularity); res->Data.Address32.Granularity);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address32.MinAddressRange, "Address32/IO 0x%x-0x%x/%d\n",
res->Data.Address32.MaxAddressRange, res->Data.Address32.MinAddressRange,
res->Data.Address32.AddressLength)); res->Data.Address32.MaxAddressRange,
res->Data.Address32.AddressLength));
set->set_iorange(dev, context, set->set_iorange(dev, context,
res->Data.Address32.MinAddressRange, res->Data.Address32.MinAddressRange,
res->Data.Address32.MaxAddressRange, res->Data.Address32.MaxAddressRange,
@ -287,14 +280,14 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
} }
} }
break; break;
case ACPI_RSTYPE_ADDRESS16: case ACPI_RSTYPE_ADDRESS16:
if (res->Data.Address16.AddressLength <= 0) if (res->Data.Address16.AddressLength <= 0)
break; break;
if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) { if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
(res->Data.Address16.ResourceType == ACPI_IO_RANGE) ? "ignored Address16 %s producer\n",
"IO" : "Memory")); res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
"IO" : "Memory"));
break; break;
} }
if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE && if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
@ -304,39 +297,44 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
break; break;
} }
if ((res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED) && if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
(res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED)) { res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address16.MinAddressRange, "Address16/Memory 0x%x/%d\n",
res->Data.Address16.AddressLength)); res->Data.Address16.MinAddressRange,
res->Data.Address16.AddressLength));
set->set_memory(dev, context, set->set_memory(dev, context,
res->Data.Address16.MinAddressRange, res->Data.Address16.MinAddressRange,
res->Data.Address16.AddressLength); res->Data.Address16.AddressLength);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address16.MinAddressRange, "Address16/IO 0x%x/%d\n",
res->Data.Address16.AddressLength)); res->Data.Address16.MinAddressRange,
res->Data.Address16.AddressLength));
set->set_ioport(dev, context, set->set_ioport(dev, context,
res->Data.Address16.MinAddressRange, res->Data.Address16.MinAddressRange,
res->Data.Address16.AddressLength); res->Data.Address16.AddressLength);
} }
} else { } else {
if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address16.MinAddressRange, "Address16/Memory 0x%x-0x%x/%d\n",
res->Data.Address16.MaxAddressRange, res->Data.Address16.MinAddressRange,
res->Data.Address16.AddressLength)); res->Data.Address16.MaxAddressRange,
res->Data.Address16.AddressLength));
set->set_memoryrange(dev, context, set->set_memoryrange(dev, context,
res->Data.Address16.MinAddressRange, res->Data.Address16.MinAddressRange,
res->Data.Address16.MaxAddressRange, res->Data.Address16.MaxAddressRange,
res->Data.Address16.AddressLength, res->Data.Address16.AddressLength,
res->Data.Address16.Granularity); res->Data.Address16.Granularity);
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x-0x%x/%d\n", ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
res->Data.Address16.MinAddressRange, "Address16/IO 0x%x-0x%x/%d\n",
res->Data.Address16.MaxAddressRange, res->Data.Address16.MinAddressRange,
res->Data.Address16.AddressLength)); res->Data.Address16.MaxAddressRange,
res->Data.Address16.AddressLength));
set->set_iorange(dev, context, set->set_iorange(dev, context,
res->Data.Address16.MinAddressRange, res->Data.Address16.MinAddressRange,
res->Data.Address16.MaxAddressRange, res->Data.Address16.MaxAddressRange,
@ -345,27 +343,27 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
} }
} }
break; break;
case ACPI_RSTYPE_ADDRESS64: case ACPI_RSTYPE_ADDRESS64:
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n")); ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
"unimplemented Address64 resource\n"));
break; break;
case ACPI_RSTYPE_EXT_IRQ: case ACPI_RSTYPE_EXT_IRQ:
/* XXX special handling? */ /* XXX special handling? */
set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts, set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
res->Data.ExtendedIrq.NumberOfInterrupts); res->Data.ExtendedIrq.NumberOfInterrupts);
break; break;
case ACPI_RSTYPE_VENDOR: case ACPI_RSTYPE_VENDOR:
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n")); ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
"unimplemented VendorSpecific resource\n"));
break; break;
default: default:
break; break;
} }
} }
AcpiOsFree(buf.Pointer); AcpiOsFree(buf.Pointer);
set->set_done(dev, context); set->set_done(dev, context);
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS (AE_OK);
} }
/* /*
@ -374,17 +372,22 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resourc
*/ */
static void acpi_res_set_init(device_t dev, void **context); static void acpi_res_set_init(device_t dev, void **context);
static void acpi_res_set_done(device_t dev, void *context); static void acpi_res_set_done(device_t dev, void *context);
static void acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length); static void acpi_res_set_ioport(device_t dev, void *context,
static void acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t base, u_int32_t length);
static void acpi_res_set_iorange(device_t dev, void *context,
u_int32_t low, u_int32_t high,
u_int32_t length, u_int32_t align); u_int32_t length, u_int32_t align);
static void acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length); static void acpi_res_set_memory(device_t dev, void *context,
static void acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t base, u_int32_t length);
static void acpi_res_set_memoryrange(device_t dev, void *context,
u_int32_t low, u_int32_t high,
u_int32_t length, u_int32_t align); u_int32_t length, u_int32_t align);
static void acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, static void acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
int count); int count);
static void acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, static void acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
int count); int count);
static void acpi_res_set_start_dependant(device_t dev, void *context, int preference); static void acpi_res_set_start_dependant(device_t dev, void *context,
int preference);
static void acpi_res_set_end_dependant(device_t dev, void *context); static void acpi_res_set_end_dependant(device_t dev, void *context);
struct acpi_parse_resource_set acpi_res_parse_set = { struct acpi_parse_resource_set acpi_res_parse_set = {
@ -429,7 +432,8 @@ acpi_res_set_done(device_t dev, void *context)
} }
static void static void
acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length) acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
u_int32_t length)
{ {
struct acpi_res_context *cp = (struct acpi_res_context *)context; struct acpi_res_context *cp = (struct acpi_res_context *)context;
@ -439,7 +443,8 @@ acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t lengt
} }
static void static void
acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align) acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
u_int32_t high, u_int32_t length, u_int32_t align)
{ {
struct acpi_res_context *cp = (struct acpi_res_context *)context; struct acpi_res_context *cp = (struct acpi_res_context *)context;
@ -449,7 +454,8 @@ acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
} }
static void static void
acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length) acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
u_int32_t length)
{ {
struct acpi_res_context *cp = (struct acpi_res_context *)context; struct acpi_res_context *cp = (struct acpi_res_context *)context;
@ -460,7 +466,8 @@ acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t lengt
} }
static void static void
acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align) acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
u_int32_t high, u_int32_t length, u_int32_t align)
{ {
struct acpi_res_context *cp = (struct acpi_res_context *)context; struct acpi_res_context *cp = (struct acpi_res_context *)context;
@ -474,13 +481,11 @@ acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count)
{ {
struct acpi_res_context *cp = (struct acpi_res_context *)context; struct acpi_res_context *cp = (struct acpi_res_context *)context;
if (cp == NULL) if (cp == NULL || irq == NULL)
return;
if (irq == NULL)
return; return;
/*This implements no resource relocation.*/ /* This implements no resource relocation. */
if(count != 1) if (count != 1)
return; return;
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1); bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
@ -491,13 +496,11 @@ acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
{ {
struct acpi_res_context *cp = (struct acpi_res_context *)context; struct acpi_res_context *cp = (struct acpi_res_context *)context;
if (cp == NULL) if (cp == NULL || drq == NULL)
return;
if (drq == NULL)
return; return;
/*This implements no resource relocation.*/ /* This implements no resource relocation. */
if(count != 1) if (count != 1)
return; return;
bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1); bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
@ -520,6 +523,7 @@ acpi_res_set_end_dependant(device_t dev, void *context)
if (cp == NULL) if (cp == NULL)
return; return;
device_printf(dev, "dependant functions not supported\n");
} }
/* /*
@ -553,20 +557,19 @@ static driver_t acpi_sysresource_driver = {
}; };
static devclass_t acpi_sysresource_devclass; static devclass_t acpi_sysresource_devclass;
DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0); DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver,
acpi_sysresource_devclass, 0, 0);
static int static int
acpi_sysresource_probe(device_t dev) acpi_sysresource_probe(device_t dev)
{ {
if (acpi_disabled("sysresource")) if (!acpi_disabled("sysresource") && acpi_MatchHid(dev, "PNP0C02"))
return(ENXIO);
if (acpi_MatchHid(dev, "PNP0C02")) {
device_set_desc(dev, "system resource"); device_set_desc(dev, "system resource");
} else { else
return(ENXIO); return (ENXIO);
}
device_quiet(dev); device_quiet(dev);
return(-100); return (-100);
} }
static int static int
@ -587,7 +590,9 @@ acpi_sysresource_attach(device_t dev)
rid = i; rid = i;
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0); res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
rid = i; rid = i;
res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE); res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
RF_SHAREABLE);
} }
return(0);
return (0);
} }

View File

@ -40,12 +40,9 @@ __FBSDID("$FreeBSD$");
#include <sys/power.h> #include <sys/power.h>
#include "acpi.h" #include "acpi.h"
#include <dev/acpica/acpivar.h> #include <dev/acpica/acpivar.h>
/* /* Hooks for the ACPI CA debugging infrastructure */
* Hooks for the ACPI CA debugging infrastructure
*/
#define _COMPONENT ACPI_THERMAL #define _COMPONENT ACPI_THERMAL
ACPI_MODULE_NAME("THERMAL") ACPI_MODULE_NAME("THERMAL")
@ -56,9 +53,11 @@ ACPI_MODULE_NAME("THERMAL")
#define TZ_NOTIFY_DEVICES 0x81 #define TZ_NOTIFY_DEVICES 0x81
#define TZ_NOTIFY_LEVELS 0x82 #define TZ_NOTIFY_LEVELS 0x82
#define TZ_POLLRATE 30 /* every 30 seconds by default */ /* Check for temperature changes every 30 seconds by default */
#define TZ_POLLRATE 30
#define TZ_NUMLEVELS 10 /* defined by ACPI spec */ /* ACPI spec defines this */
#define TZ_NUMLEVELS 10
struct acpi_tz_zone { struct acpi_tz_zone {
int ac[TZ_NUMLEVELS]; int ac[TZ_NUMLEVELS];
ACPI_BUFFER al[TZ_NUMLEVELS]; ACPI_BUFFER al[TZ_NUMLEVELS];
@ -74,45 +73,46 @@ struct acpi_tz_zone {
struct acpi_tz_softc { struct acpi_tz_softc {
device_t tz_dev; /* device handle */ device_t tz_dev;
ACPI_HANDLE tz_handle; /* thermal zone handle */ ACPI_HANDLE tz_handle; /*Thermal zone handle*/
int tz_temperature; /* current temperature */ int tz_temperature; /*Current temperature*/
int tz_active; /* current active cooling */ int tz_active; /*Current active cooling*/
#define TZ_ACTIVE_NONE -1 #define TZ_ACTIVE_NONE -1
int tz_requested; /* user-requested minimum active cooling */ int tz_requested; /*Minimum active cooling*/
int tz_thflags; /* current temperature-related flags */ int tz_thflags; /*Current temp-related flags*/
#define TZ_THFLAG_NONE 0 #define TZ_THFLAG_NONE 0
#define TZ_THFLAG_PSV (1<<0) #define TZ_THFLAG_PSV (1<<0)
#define TZ_THFLAG_HOT (1<<2) #define TZ_THFLAG_HOT (1<<2)
#define TZ_THFLAG_CRT (1<<3) #define TZ_THFLAG_CRT (1<<3)
int tz_flags; int tz_flags;
#define TZ_FLAG_NO_SCP (1<<0) /* no _SCP method */ #define TZ_FLAG_NO_SCP (1<<0) /*No _SCP method*/
#define TZ_FLAG_GETPROFILE (1<<1) /* fetch power_profile in timeout */ #define TZ_FLAG_GETPROFILE (1<<1) /*Get power_profile in timeout*/
struct timespec tz_cooling_started; /* current cooling starting time */ struct timespec tz_cooling_started;
/*Current cooling starting time*/
struct sysctl_ctx_list tz_sysctl_ctx; /* sysctl tree */ struct sysctl_ctx_list tz_sysctl_ctx;
struct sysctl_oid *tz_sysctl_tree; struct sysctl_oid *tz_sysctl_tree;
struct acpi_tz_zone tz_zone; /* thermal zone parameters */ struct acpi_tz_zone tz_zone; /*Thermal zone parameters*/
int tz_tmp_updating; int tz_tmp_updating;
}; };
static int acpi_tz_probe(device_t dev); static int acpi_tz_probe(device_t dev);
static int acpi_tz_attach(device_t dev); static int acpi_tz_attach(device_t dev);
static int acpi_tz_establish(struct acpi_tz_softc *sc); static int acpi_tz_establish(struct acpi_tz_softc *sc);
static void acpi_tz_monitor(struct acpi_tz_softc *sc); static void acpi_tz_monitor(void *Context);
static void acpi_tz_all_off(struct acpi_tz_softc *sc); static void acpi_tz_all_off(struct acpi_tz_softc *sc);
static void acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg); static void acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg);
static void acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg); static void acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg);
static void acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data); static void acpi_tz_getparam(struct acpi_tz_softc *sc, char *node,
int *data);
static void acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what); static void acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what);
static int acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS);
static void acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context); static void acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify,
void *context);
static void acpi_tz_timeout(struct acpi_tz_softc *sc); static void acpi_tz_timeout(struct acpi_tz_softc *sc);
static void acpi_tz_power_profile(void *arg); static void acpi_tz_power_profile(void *arg);
static void acpi_tz_thread(void *arg); static void acpi_tz_thread(void *arg);
static struct proc *acpi_tz_proc;
static device_method_t acpi_tz_methods[] = { static device_method_t acpi_tz_methods[] = {
/* Device interface */ /* Device interface */
@ -134,9 +134,13 @@ DRIVER_MODULE(acpi_tz, acpi, acpi_tz_driver, acpi_tz_devclass, 0, 0);
static struct sysctl_ctx_list acpi_tz_sysctl_ctx; static struct sysctl_ctx_list acpi_tz_sysctl_ctx;
static struct sysctl_oid *acpi_tz_sysctl_tree; static struct sysctl_oid *acpi_tz_sysctl_tree;
static int acpi_tz_min_runtime = 0;/* minimum cooling run time */ /* Minimum cooling run time */
static int acpi_tz_min_runtime = 0;
static int acpi_tz_polling_rate = TZ_POLLRATE; static int acpi_tz_polling_rate = TZ_POLLRATE;
/* Timezone polling thread */
static struct proc *acpi_tz_proc;
/* /*
* Match an ACPI thermal zone. * Match an ACPI thermal zone.
*/ */
@ -148,17 +152,16 @@ acpi_tz_probe(device_t dev)
ACPI_LOCK; ACPI_LOCK;
/* no FUNCTION_TRACE - too noisy */ /* No FUNCTION_TRACE - too noisy */
if ((acpi_get_type(dev) == ACPI_TYPE_THERMAL) && if (acpi_get_type(dev) == ACPI_TYPE_THERMAL && !acpi_disabled("thermal")) {
!acpi_disabled("thermal")) {
device_set_desc(dev, "thermal zone"); device_set_desc(dev, "thermal zone");
result = -10; result = -10;
} else { } else {
result = ENXIO; result = ENXIO;
} }
ACPI_UNLOCK; ACPI_UNLOCK;
return(result); return (result);
} }
/* /*
@ -205,12 +208,13 @@ acpi_tz_attach(device_t dev)
acpi_sc = acpi_device_get_parent_softc(dev); acpi_sc = acpi_device_get_parent_softc(dev);
sysctl_ctx_init(&acpi_tz_sysctl_ctx); sysctl_ctx_init(&acpi_tz_sysctl_ctx);
acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx, acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
OID_AUTO, "thermal", CTLFLAG_RD, 0, ""); OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx, SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
SYSCTL_CHILDREN(acpi_tz_sysctl_tree), SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
OID_AUTO, "min_runtime", CTLFLAG_RD | CTLFLAG_RW, OID_AUTO, "min_runtime", CTLFLAG_RD | CTLFLAG_RW,
&acpi_tz_min_runtime, 0, "minimum cooling run time in sec"); &acpi_tz_min_runtime, 0,
"minimum cooling run time in sec");
SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx, SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
SYSCTL_CHILDREN(acpi_tz_sysctl_tree), SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
OID_AUTO, "polling_rate", CTLFLAG_RD | CTLFLAG_RW, OID_AUTO, "polling_rate", CTLFLAG_RD | CTLFLAG_RW,
@ -219,8 +223,8 @@ acpi_tz_attach(device_t dev)
sysctl_ctx_init(&sc->tz_sysctl_ctx); sysctl_ctx_init(&sc->tz_sysctl_ctx);
sprintf(oidname, "tz%d", device_get_unit(dev)); sprintf(oidname, "tz%d", device_get_unit(dev));
sc->tz_sysctl_tree = SYSCTL_ADD_NODE(&sc->tz_sysctl_ctx, sc->tz_sysctl_tree = SYSCTL_ADD_NODE(&sc->tz_sysctl_ctx,
SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO, SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
oidname, CTLFLAG_RD, 0, ""); OID_AUTO, oidname, CTLFLAG_RD, 0, "");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree), SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "temperature", CTLFLAG_RD, OID_AUTO, "temperature", CTLFLAG_RD,
&sc->tz_temperature, 0, "current thermal zone temperature"); &sc->tz_temperature, 0, "current thermal zone temperature");
@ -244,7 +248,6 @@ acpi_tz_attach(device_t dev)
OID_AUTO, "_ACx", CTLFLAG_RD, &sc->tz_zone.ac, OID_AUTO, "_ACx", CTLFLAG_RD, &sc->tz_zone.ac,
sizeof(sc->tz_zone.ac), "I", ""); sizeof(sc->tz_zone.ac), "I", "");
/* /*
* Register our power profile event handler, and flag it for a manual * Register our power profile event handler, and flag it for a manual
* invocation by our timeout. We defer it like this so that the rest * invocation by our timeout. We defer it like this so that the rest
@ -266,7 +269,8 @@ acpi_tz_attach(device_t dev)
error = kthread_create(acpi_tz_thread, NULL, &acpi_tz_proc, error = kthread_create(acpi_tz_thread, NULL, &acpi_tz_proc,
RFHIGHPID, 0, "acpi_thermal"); RFHIGHPID, 0, "acpi_thermal");
if (error != 0) { if (error != 0) {
device_printf(sc->tz_dev, "could not create thread - %d", error); device_printf(sc->tz_dev, "could not create thread - %d",
error);
goto out; goto out;
} }
} }
@ -274,7 +278,7 @@ acpi_tz_attach(device_t dev)
out: out:
ACPI_UNLOCK; ACPI_UNLOCK;
return_VALUE(error); return_VALUE (error);
} }
/* /*
@ -293,9 +297,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
ACPI_ASSERTLOCK; ACPI_ASSERTLOCK;
/* /* Power everything off and erase any existing state. */
* Power everything off and erase any existing state.
*/
acpi_tz_all_off(sc); acpi_tz_all_off(sc);
for (i = 0; i < TZ_NUMLEVELS; i++) for (i = 0; i < TZ_NUMLEVELS; i++)
if (sc->tz_zone.al[i].Pointer != NULL) if (sc->tz_zone.al[i].Pointer != NULL)
@ -304,9 +306,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
AcpiOsFree(sc->tz_zone.psl.Pointer); AcpiOsFree(sc->tz_zone.psl.Pointer);
bzero(&sc->tz_zone, sizeof(sc->tz_zone)); bzero(&sc->tz_zone, sizeof(sc->tz_zone));
/* /* Evaluate thermal zone parameters. */
* Evaluate thermal zone parameters.
*/
for (i = 0; i < TZ_NUMLEVELS; i++) { for (i = 0; i < TZ_NUMLEVELS; i++) {
sprintf(nbuf, "_AC%d", i); sprintf(nbuf, "_AC%d", i);
acpi_tz_getparam(sc, nbuf, &sc->tz_zone.ac[i]); acpi_tz_getparam(sc, nbuf, &sc->tz_zone.ac[i]);
@ -316,11 +316,11 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
AcpiEvaluateObject(sc->tz_handle, nbuf, NULL, &sc->tz_zone.al[i]); AcpiEvaluateObject(sc->tz_handle, nbuf, NULL, &sc->tz_zone.al[i]);
obj = (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer; obj = (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer;
if (obj != NULL) { if (obj != NULL) {
/* should be a package containing a list of power objects */ /* Should be a package containing a list of power objects */
if (obj->Type != ACPI_TYPE_PACKAGE) { if (obj->Type != ACPI_TYPE_PACKAGE) {
device_printf(sc->tz_dev, "%s has unknown object type %d, rejecting\n", device_printf(sc->tz_dev, "%s has unknown type %d, rejecting\n",
nbuf, obj->Type); nbuf, obj->Type);
return_VALUE(ENXIO); return_VALUE (ENXIO);
} }
} }
} }
@ -352,7 +352,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
*/ */
acpi_tz_all_off(sc); acpi_tz_all_off(sc);
return_VALUE(0); return_VALUE (0);
} }
static char *aclevel_string[] = { static char *aclevel_string[] = {
@ -362,9 +362,8 @@ static char *aclevel_string[] = {
static __inline const char * static __inline const char *
acpi_tz_aclevel_string(int active) acpi_tz_aclevel_string(int active)
{ {
if (active < -1 || active >= TZ_NUMLEVELS) { if (active < -1 || active >= TZ_NUMLEVELS)
return (aclevel_string[0]); return (aclevel_string[0]);
}
return (aclevel_string[active+1]); return (aclevel_string[active+1]);
} }
@ -373,27 +372,27 @@ acpi_tz_aclevel_string(int active)
* Evaluate the condition of a thermal zone, take appropriate actions. * Evaluate the condition of a thermal zone, take appropriate actions.
*/ */
static void static void
acpi_tz_monitor(struct acpi_tz_softc *sc) acpi_tz_monitor(void *Context)
{ {
struct acpi_tz_softc *sc;
struct timespec curtime;
int temp; int temp;
int i; int i;
int newactive, newflags; int newactive, newflags;
struct timespec curtime;
ACPI_STATUS status; ACPI_STATUS status;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
ACPI_ASSERTLOCK; ACPI_ASSERTLOCK;
if (sc->tz_tmp_updating) { sc = (struct acpi_tz_softc *)Context;
if (sc->tz_tmp_updating)
goto out; goto out;
}
sc->tz_tmp_updating = 1; sc->tz_tmp_updating = 1;
/* /* Get the current temperature. */
* Get the current temperature. status = acpi_EvaluateInteger(sc->tz_handle, "_TMP", &temp);
*/ if (ACPI_FAILURE(status)) {
if (ACPI_FAILURE(status = acpi_EvaluateInteger(sc->tz_handle, "_TMP", &temp))) {
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
"error fetching current temperature -- %s\n", "error fetching current temperature -- %s\n",
AcpiFormatException(status)); AcpiFormatException(status));
@ -414,9 +413,10 @@ acpi_tz_monitor(struct acpi_tz_softc *sc)
if ((sc->tz_zone.ac[i] != -1) && (temp >= sc->tz_zone.ac[i])) { if ((sc->tz_zone.ac[i] != -1) && (temp >= sc->tz_zone.ac[i])) {
newactive = i; newactive = i;
if (sc->tz_active != newactive) { if (sc->tz_active != newactive) {
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev,
"_AC%d: temperature %d.%d >= setpoint %d.%d\n", i, acpi_device_get_parent_softc(sc->tz_dev),
TZ_KELVTOC(temp), TZ_KELVTOC(sc->tz_zone.ac[i])); "_AC%d: temperature %d.%d >= setpoint %d.%d\n", i,
TZ_KELVTOC(temp), TZ_KELVTOC(sc->tz_zone.ac[i]));
getnanotime(&sc->tz_cooling_started); getnanotime(&sc->tz_cooling_started);
} }
} }
@ -428,14 +428,14 @@ acpi_tz_monitor(struct acpi_tz_softc *sc)
*/ */
if (acpi_tz_min_runtime > 0 && sc->tz_active != TZ_ACTIVE_NONE && if (acpi_tz_min_runtime > 0 && sc->tz_active != TZ_ACTIVE_NONE &&
(newactive == TZ_ACTIVE_NONE || newactive > sc->tz_active)) { (newactive == TZ_ACTIVE_NONE || newactive > sc->tz_active)) {
getnanotime(&curtime); getnanotime(&curtime);
timespecsub(&curtime, &sc->tz_cooling_started); timespecsub(&curtime, &sc->tz_cooling_started);
if (curtime.tv_sec < acpi_tz_min_runtime) { if (curtime.tv_sec < acpi_tz_min_runtime)
newactive = sc->tz_active; newactive = sc->tz_active;
}
} }
/* handle user override of active mode */ /* Handle user override of active mode */
if (sc->tz_requested > newactive) if (sc->tz_requested > newactive)
newactive = sc->tz_requested; newactive = sc->tz_requested;
@ -448,30 +448,28 @@ acpi_tz_monitor(struct acpi_tz_softc *sc)
if ((sc->tz_zone.crt != -1) && (temp >= sc->tz_zone.crt)) if ((sc->tz_zone.crt != -1) && (temp >= sc->tz_zone.crt))
newflags |= TZ_THFLAG_CRT; newflags |= TZ_THFLAG_CRT;
/* /* If the active cooling state has changed, we have to switch things. */
* If the active cooling state has changed, we have to switch things.
*/
if (newactive != sc->tz_active) { if (newactive != sc->tz_active) {
/* Turn off the cooling devices that are on, if any are */
/* turn off the cooling devices that are on, if any are */
if (sc->tz_active != TZ_ACTIVE_NONE) if (sc->tz_active != TZ_ACTIVE_NONE)
acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_zone.al[sc->tz_active].Pointer, acpi_ForeachPackageObject(
acpi_tz_switch_cooler_off, sc); (ACPI_OBJECT *)sc->tz_zone.al[sc->tz_active].Pointer,
acpi_tz_switch_cooler_off, sc);
/* turn on cooling devices that are required, if any are */ /* Turn on cooling devices that are required, if any are */
if (newactive != TZ_ACTIVE_NONE) if (newactive != TZ_ACTIVE_NONE) {
acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_zone.al[newactive].Pointer, acpi_ForeachPackageObject(
acpi_tz_switch_cooler_on, sc); (ACPI_OBJECT *)sc->tz_zone.al[newactive].Pointer,
acpi_tz_switch_cooler_on, sc);
}
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
"switched from %s to %s: %d.%dC\n", "switched from %s to %s: %d.%dC\n",
acpi_tz_aclevel_string(sc->tz_active), acpi_tz_aclevel_string(sc->tz_active),
acpi_tz_aclevel_string(newactive), TZ_KELVTOC(temp)); acpi_tz_aclevel_string(newactive), TZ_KELVTOC(temp));
sc->tz_active = newactive; sc->tz_active = newactive;
} }
/* /* XXX (de)activate any passive cooling that may be required. */
* XXX (de)activate any passive cooling that may be required.
*/
/* /*
* If we have just become _HOT or _CRT, warn the user. * If we have just become _HOT or _CRT, warn the user.
@ -479,9 +477,11 @@ acpi_tz_monitor(struct acpi_tz_softc *sc)
* We should actually shut down at this point, but it's not clear * We should actually shut down at this point, but it's not clear
* that some systems don't actually map _CRT to the same value as _AC0. * that some systems don't actually map _CRT to the same value as _AC0.
*/ */
if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) && if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0 &&
!(sc->tz_thflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT))) { (sc->tz_thflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) == 0) {
device_printf(sc->tz_dev, "WARNING - current temperature (%d.%dC) exceeds system limits\n",
device_printf(sc->tz_dev,
"WARNING - current temperature (%d.%dC) exceeds system limits\n",
TZ_KELVTOC(sc->tz_temperature)); TZ_KELVTOC(sc->tz_temperature));
/* shutdown_nice(RB_POWEROFF);*/ /* shutdown_nice(RB_POWEROFF);*/
} }
@ -504,9 +504,7 @@ acpi_tz_all_off(struct acpi_tz_softc *sc)
ACPI_ASSERTLOCK; ACPI_ASSERTLOCK;
/* /* Scan all the _ALx objects and turn them all off. */
* Scan all the _ALx objects, and turn them all off.
*/
for (i = 0; i < TZ_NUMLEVELS; i++) { for (i = 0; i < TZ_NUMLEVELS; i++) {
if (sc->tz_zone.al[i].Pointer == NULL) if (sc->tz_zone.al[i].Pointer == NULL)
continue; continue;
@ -520,6 +518,7 @@ acpi_tz_all_off(struct acpi_tz_softc *sc)
sc->tz_active = TZ_ACTIVE_NONE; sc->tz_active = TZ_ACTIVE_NONE;
sc->tz_thflags = TZ_THFLAG_NONE; sc->tz_thflags = TZ_THFLAG_NONE;
return_VOID; return_VOID;
} }
@ -538,13 +537,14 @@ acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg)
switch(obj->Type) { switch(obj->Type) {
case ACPI_TYPE_ANY: case ACPI_TYPE_ANY:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n", acpi_name(obj->Reference.Handle))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n",
acpi_name(obj->Reference.Handle)));
acpi_pwr_switch_consumer(obj->Reference.Handle, ACPI_STATE_D3); acpi_pwr_switch_consumer(obj->Reference.Handle, ACPI_STATE_D3);
break; break;
case ACPI_TYPE_STRING: case ACPI_TYPE_STRING:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n", obj->String.Pointer)); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n",
obj->String.Pointer));
/* /*
* Find the handle for the device and turn it off. * Find the handle for the device and turn it off.
@ -556,12 +556,13 @@ acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg)
if (ACPI_SUCCESS(AcpiGetHandle(NULL, obj->String.Pointer, &cooler))) if (ACPI_SUCCESS(AcpiGetHandle(NULL, obj->String.Pointer, &cooler)))
acpi_pwr_switch_consumer(cooler, ACPI_STATE_D3); acpi_pwr_switch_consumer(cooler, ACPI_STATE_D3);
break; break;
default: default:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to handle unsupported object type %d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
obj->Type)); "called to handle unsupported object type %d\n",
obj->Type));
break; break;
} }
return_VOID; return_VOID;
} }
@ -584,17 +585,20 @@ acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg)
switch(obj->Type) { switch(obj->Type) {
case ACPI_TYPE_ANY: case ACPI_TYPE_ANY:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n", acpi_name(obj->Reference.Handle))); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n",
acpi_name(obj->Reference.Handle)));
if (ACPI_FAILURE(status = acpi_pwr_switch_consumer(obj->Reference.Handle, ACPI_STATE_D0))) { status = acpi_pwr_switch_consumer(obj->Reference.Handle, ACPI_STATE_D0);
if (ACPI_FAILURE(status)) {
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
"failed to activate %s - %s\n", acpi_name(obj->Reference.Handle), "failed to activate %s - %s\n",
AcpiFormatException(status)); acpi_name(obj->Reference.Handle),
AcpiFormatException(status));
} }
break; break;
case ACPI_TYPE_STRING: case ACPI_TYPE_STRING:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n", obj->String.Pointer)); ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n",
obj->String.Pointer));
/* /*
* Find the handle for the device and turn it off. * Find the handle for the device and turn it off.
@ -604,23 +608,25 @@ acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg)
* XXX This may not always be the case. * XXX This may not always be the case.
*/ */
if (ACPI_SUCCESS(AcpiGetHandle(NULL, obj->String.Pointer, &cooler))) { if (ACPI_SUCCESS(AcpiGetHandle(NULL, obj->String.Pointer, &cooler))) {
if (ACPI_FAILURE(status = acpi_pwr_switch_consumer(cooler, ACPI_STATE_D0))) { status = acpi_pwr_switch_consumer(cooler, ACPI_STATE_D0);
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), if (ACPI_FAILURE(status)) {
"failed to activate %s - %s\n", ACPI_VPRINT(sc->tz_dev,
obj->String.Pointer, AcpiFormatException(status)); acpi_device_get_parent_softc(sc->tz_dev),
"failed to activate %s - %s\n",
obj->String.Pointer, AcpiFormatException(status));
} }
} else { } else {
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
"couldn't find %s\n", obj->String.Pointer); "couldn't find %s\n", obj->String.Pointer);
} }
break; break;
default: default:
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to handle unsupported object type %d\n", ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "unsupported object type %d\n",
obj->Type)); obj->Type));
break; break;
} }
return_VOID;
return_VOID;
} }
/* /*
@ -637,9 +643,10 @@ acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
if (ACPI_FAILURE(acpi_EvaluateInteger(sc->tz_handle, node, data))) { if (ACPI_FAILURE(acpi_EvaluateInteger(sc->tz_handle, node, data))) {
*data = -1; *data = -1;
} else { } else {
ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "%s.%s = %d\n", acpi_name(sc->tz_handle), ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "%s.%s = %d\n",
node, *data)); acpi_name(sc->tz_handle), node, *data));
} }
return_VOID; return_VOID;
} }
@ -650,7 +657,7 @@ acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
static void static void
acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what) acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what)
{ {
if ((*val != -1) && ((*val < TZ_ZEROC) || (*val > (TZ_ZEROC + 1500)))) { if (*val != -1 && (*val < TZ_ZEROC || *val > TZ_ZEROC + 1500)) {
device_printf(sc->tz_dev, "%s value is absurd, ignored (%d.%dC)\n", device_printf(sc->tz_dev, "%s value is absurd, ignored (%d.%dC)\n",
what, TZ_KELVTOC(*val)); what, TZ_KELVTOC(*val));
*val = -1; *val = -1;
@ -674,23 +681,21 @@ acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS)
active = sc->tz_active; active = sc->tz_active;
error = sysctl_handle_int(oidp, &active, 0, req); error = sysctl_handle_int(oidp, &active, 0, req);
/* error or no new value */ /* Error or no new value */
if ((error != 0) || (req->newptr == NULL)) if (error != 0 || req->newptr == NULL)
goto out; goto out;
if (active < -1 || active >= TZ_NUMLEVELS) {
/* range check */
if ((active < -1) || (active >= TZ_NUMLEVELS)) {
error = EINVAL; error = EINVAL;
goto out; goto out;
} }
/* set new preferred level and re-switch */ /* Set new preferred level and re-switch */
sc->tz_requested = active; sc->tz_requested = active;
acpi_tz_monitor(sc); acpi_tz_monitor(sc);
out: out:
ACPI_UNLOCK; ACPI_UNLOCK;
return(error); return (error);
} }
/* /*
@ -707,19 +712,21 @@ acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
switch(notify) { switch(notify) {
case TZ_NOTIFY_TEMPERATURE: case TZ_NOTIFY_TEMPERATURE:
/* temperature change occurred */ /* Temperature change occurred */
AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_monitor, sc); AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, acpi_tz_monitor, sc);
break; break;
case TZ_NOTIFY_DEVICES: case TZ_NOTIFY_DEVICES:
case TZ_NOTIFY_LEVELS: case TZ_NOTIFY_LEVELS:
/* zone devices/setpoints changed */ /* Zone devices/setpoints changed */
AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_establish, sc); AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
(OSD_EXECUTION_CALLBACK)acpi_tz_establish, sc);
break; break;
default: default:
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
"unknown Notify event 0x%x\n", notify); "unknown Notify event 0x%x\n", notify);
break; break;
} }
return_VOID; return_VOID;
} }
@ -729,8 +736,7 @@ acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
static void static void
acpi_tz_timeout(struct acpi_tz_softc *sc) acpi_tz_timeout(struct acpi_tz_softc *sc)
{ {
/* Do we need to get the power profile settings? */
/* do we need to get the power profile settings? */
if (sc->tz_flags & TZ_FLAG_GETPROFILE) { if (sc->tz_flags & TZ_FLAG_GETPROFILE) {
acpi_tz_power_profile((void *)sc); acpi_tz_power_profile((void *)sc);
sc->tz_flags &= ~TZ_FLAG_GETPROFILE; sc->tz_flags &= ~TZ_FLAG_GETPROFILE;
@ -738,7 +744,7 @@ acpi_tz_timeout(struct acpi_tz_softc *sc)
ACPI_ASSERTLOCK; ACPI_ASSERTLOCK;
/* check the current temperature and take action based on it */ /* Check the current temperature and take action based on it */
acpi_tz_monitor(sc); acpi_tz_monitor(sc);
/* XXX passive cooling actions? */ /* XXX passive cooling actions? */
@ -762,32 +768,36 @@ acpi_tz_power_profile(void *arg)
ACPI_LOCK_DECL; ACPI_LOCK_DECL;
state = power_profile_get_state(); state = power_profile_get_state();
if (state != POWER_PROFILE_PERFORMANCE && if (state != POWER_PROFILE_PERFORMANCE && state != POWER_PROFILE_ECONOMY)
state != POWER_PROFILE_ECONOMY) { return;
return;
}
ACPI_LOCK; ACPI_LOCK;
/* check that we haven't decided there's no _SCP method */ /* check that we haven't decided there's no _SCP method */
if (!(sc->tz_flags & TZ_FLAG_NO_SCP)) { if ((sc->tz_flags & TZ_FLAG_NO_SCP) == 0) {
/* call _SCP to set the new profile */ /* Call _SCP to set the new profile */
obj.Type = ACPI_TYPE_INTEGER; obj.Type = ACPI_TYPE_INTEGER;
obj.Integer.Value = (state == POWER_PROFILE_PERFORMANCE) ? 0 : 1; obj.Integer.Value = (state == POWER_PROFILE_PERFORMANCE) ? 0 : 1;
args.Count = 1; args.Count = 1;
args.Pointer = &obj; args.Pointer = &obj;
if (ACPI_FAILURE(status = AcpiEvaluateObject(sc->tz_handle, "_SCP", &args, NULL))) { status = AcpiEvaluateObject(sc->tz_handle, "_SCP", &args, NULL);
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) if (status != AE_NOT_FOUND)
ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), ACPI_VPRINT(sc->tz_dev,
"can't evaluate %s._SCP - %s\n", acpi_name(sc->tz_handle), acpi_device_get_parent_softc(sc->tz_dev),
AcpiFormatException(status)); "can't evaluate %s._SCP - %s\n",
acpi_name(sc->tz_handle),
AcpiFormatException(status));
sc->tz_flags |= TZ_FLAG_NO_SCP; sc->tz_flags |= TZ_FLAG_NO_SCP;
} else { } else {
/* we have to re-evaluate the entire zone now */ /* We have to re-evaluate the entire zone now */
AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_establish, sc); AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
(OSD_EXECUTION_CALLBACK)acpi_tz_establish,
sc);
} }
} }
ACPI_UNLOCK; ACPI_UNLOCK;
} }
@ -803,12 +813,11 @@ acpi_tz_thread(void *arg)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
devs = NULL; devs = NULL;
devcount = 0; devcount = 0;
for (;;) { for (;;) {
tsleep(&acpi_tz_proc, PZERO, "nothing", hz * acpi_tz_polling_rate); tsleep(&acpi_tz_proc, PZERO, "tzpoll", hz * acpi_tz_polling_rate);
#if __FreeBSD_version >= 500000 #if __FreeBSD_version >= 500000
mtx_lock(&Giant); mtx_lock(&Giant);

View File

@ -42,7 +42,6 @@
#include <sys/rman.h> #include <sys/rman.h>
#include "acpi.h" #include "acpi.h"
#include <dev/acpica/acpivar.h> #include <dev/acpica/acpivar.h>
#include <dev/pci/pcivar.h> #include <dev/pci/pcivar.h>
@ -52,16 +51,14 @@
* Based on the i386-only mp_clock.c by <phk@FreeBSD.ORG>. * Based on the i386-only mp_clock.c by <phk@FreeBSD.ORG>.
*/ */
/* /* Hooks for the ACPI CA debugging infrastructure */
* Hooks for the ACPI CA debugging infrastructure
*/
#define _COMPONENT ACPI_SYSTEM #define _COMPONENT ACPI_SYSTEM
ACPI_MODULE_NAME("TIMER") ACPI_MODULE_NAME("TIMER")
static device_t acpi_timer_dev; static device_t acpi_timer_dev;
struct resource *acpi_timer_reg; struct resource *acpi_timer_reg;
static u_int acpi_timer_frequency = 14318182/4; static u_int acpi_timer_frequency = 14318182 / 4;
static void acpi_timer_identify(driver_t *driver, device_t parent); static void acpi_timer_identify(driver_t *driver, device_t parent);
static int acpi_timer_probe(device_t dev); static int acpi_timer_probe(device_t dev);
@ -71,12 +68,9 @@ static unsigned acpi_timer_get_timecount_safe(struct timecounter *tc);
static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS); static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS);
static void acpi_timer_test(void); static void acpi_timer_test(void);
static u_int32_t read_counter(void); static uint32_t read_counter(void);
static int test_counter(void); static int test_counter(void);
/*
* Driver hung off ACPI.
*/
static device_method_t acpi_timer_methods[] = { static device_method_t acpi_timer_methods[] = {
DEVMETHOD(device_identify, acpi_timer_identify), DEVMETHOD(device_identify, acpi_timer_identify),
DEVMETHOD(device_probe, acpi_timer_probe), DEVMETHOD(device_probe, acpi_timer_probe),
@ -94,9 +88,6 @@ static driver_t acpi_timer_driver = {
static devclass_t acpi_timer_devclass; static devclass_t acpi_timer_devclass;
DRIVER_MODULE(acpi_timer, acpi, acpi_timer_driver, acpi_timer_devclass, 0, 0); DRIVER_MODULE(acpi_timer, acpi, acpi_timer_driver, acpi_timer_devclass, 0, 0);
/*
* Timecounter.
*/
static struct timecounter acpi_timer_timecounter = { static struct timecounter acpi_timer_timecounter = {
acpi_timer_get_timecount_safe, acpi_timer_get_timecount_safe,
0, 0,
@ -106,52 +97,55 @@ static struct timecounter acpi_timer_timecounter = {
1000 1000
}; };
static uint32_t
static u_int32_t
read_counter() read_counter()
{ {
bus_space_handle_t bsh; bus_space_handle_t bsh;
bus_space_tag_t bst; bus_space_tag_t bst;
u_int32_t tv; u_int32_t tv;
bsh = rman_get_bushandle(acpi_timer_reg); bsh = rman_get_bushandle(acpi_timer_reg);
bst = rman_get_bustag(acpi_timer_reg); bst = rman_get_bustag(acpi_timer_reg);
tv = bus_space_read_4(bst, bsh, 0); tv = bus_space_read_4(bst, bsh, 0);
bus_space_barrier(bst, bsh, 0, 4, BUS_SPACE_BARRIER_READ); bus_space_barrier(bst, bsh, 0, 4, BUS_SPACE_BARRIER_READ);
return (tv);
return (tv);
} }
#define N 2000 #define N 2000
static int static int
test_counter() test_counter()
{ {
int min, max, n, delta; u_int last, this;
unsigned last, this; int min, max, n, delta;
min = 10000000; min = 10000000;
max = 0; max = 0;
last = read_counter(); last = read_counter();
for (n = 0; n < N; n++) { for (n = 0; n < N; n++) {
this = read_counter(); this = read_counter();
delta = (this - last) & 0xffffff; delta = (this - last) & 0xffffff;
if (delta > max) if (delta > max)
max = delta; max = delta;
else if (delta < min) else if (delta < min)
min = delta; min = delta;
last = this; last = this;
} }
if (max - min > 2) if (max - min > 2)
n = 0; n = 0;
else if (min < 0 || max == 0) else if (min < 0 || max == 0)
n = 0; n = 0;
else else
n = 1; n = 1;
if (bootverbose) if (bootverbose) {
printf("ACPI timer looks %s min = %d, max = %d, width = %d\n", printf("ACPI timer looks %s min = %d, max = %d, width = %d\n",
n ? "GOOD" : "BAD ", n ? "GOOD" : "BAD ",
min, max, max - min); min, max, max - min);
return (n); }
return (n);
} }
#undef N
/* /*
* Locate the ACPI timer using the FADT, set up and allocate the I/O resources * Locate the ACPI timer using the FADT, set up and allocate the I/O resources
@ -167,10 +161,7 @@ acpi_timer_identify(driver_t *driver, device_t parent)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (acpi_disabled("timer")) if (acpi_disabled("timer") || AcpiGbl_FADT == NULL)
return_VOID;
if (AcpiGbl_FADT == NULL)
return_VOID; return_VOID;
if ((dev = BUS_ADD_CHILD(parent, 0, "acpi_timer", 0)) == NULL) { if ((dev = BUS_ADD_CHILD(parent, 0, "acpi_timer", 0)) == NULL) {
@ -188,7 +179,7 @@ acpi_timer_identify(driver_t *driver, device_t parent)
acpi_timer_reg = bus_alloc_resource(dev, rtype, &rid, 0, ~0, 1, RF_ACTIVE); acpi_timer_reg = bus_alloc_resource(dev, rtype, &rid, 0, ~0, 1, RF_ACTIVE);
if (acpi_timer_reg == NULL) { if (acpi_timer_reg == NULL) {
device_printf(dev, "couldn't allocate I/O resource (%s 0x%lx)\n", device_printf(dev, "couldn't allocate I/O resource (%s 0x%lx)\n",
(rtype == SYS_RES_IOPORT) ? "port" : "mem", rstart); rtype == SYS_RES_IOPORT ? "port" : "mem", rstart);
return_VOID; return_VOID;
} }
if (testenv("debug.acpi.timer_test")) if (testenv("debug.acpi.timer_test"))
@ -207,8 +198,8 @@ acpi_timer_identify(driver_t *driver, device_t parent)
} }
tc_init(&acpi_timer_timecounter); tc_init(&acpi_timer_timecounter);
sprintf(desc, "%d-bit timer at 3.579545MHz", (AcpiGbl_FADT->TmrValExt) sprintf(desc, "%d-bit timer at 3.579545MHz",
? 32 : 24); AcpiGbl_FADT->TmrValExt ? 32 : 24);
device_set_desc_copy(dev, desc); device_set_desc_copy(dev, desc);
return_VOID; return_VOID;
@ -218,14 +209,15 @@ static int
acpi_timer_probe(device_t dev) acpi_timer_probe(device_t dev)
{ {
if (dev == acpi_timer_dev) if (dev == acpi_timer_dev)
return(0); return (0);
return(ENXIO);
return (ENXIO);
} }
static int static int
acpi_timer_attach(device_t dev) acpi_timer_attach(device_t dev)
{ {
return(0); return (0);
} }
/* /*
@ -252,7 +244,8 @@ acpi_timer_get_timecount_safe(struct timecounter *tc)
u1 = u2; u1 = u2;
u2 = u3; u2 = u3;
u3 = read_counter(); u3 = read_counter();
} while (u1 > u2 || u2 > u3 || (u3 - u1) > 15); } while (u1 > u2 || u2 > u3 || u3 - u1 > 15);
return (u2); return (u2);
} }
@ -273,6 +266,7 @@ acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS)
acpi_timer_frequency = freq; acpi_timer_frequency = freq;
acpi_timer_timecounter.tc_frequency = acpi_timer_frequency; acpi_timer_timecounter.tc_frequency = acpi_timer_frequency;
} }
return (error); return (error);
} }
@ -295,12 +289,13 @@ acpi_timer_test(void)
device_printf(acpi_timer_dev, "timer test in progress, reboot to quit.\n"); device_printf(acpi_timer_dev, "timer test in progress, reboot to quit.\n");
for (;;) { for (;;) {
/* /*
* The failure case is where u3 > u1, but u2 does not fall between the two, * The failure case is where u3 > u1, but u2 does not fall between
* ie. it contains garbage. * the two, ie. it contains garbage.
*/ */
if (u3 > u1) { if (u3 > u1) {
if ((u2 < u1) || (u2 > u3)) if (u2 < u1 || u2 > u3)
device_printf(acpi_timer_dev, "timer is not monotonic: 0x%08x,0x%08x,0x%08x\n", device_printf(acpi_timer_dev,
"timer is not monotonic: 0x%08x,0x%08x,0x%08x\n",
u1, u2, u3); u1, u2, u3);
} }
u1 = u2; u1 = u2;
@ -359,7 +354,8 @@ static driver_t acpi_timer_pci_driver = {
}; };
devclass_t acpi_timer_pci_devclass; devclass_t acpi_timer_pci_devclass;
DRIVER_MODULE(acpi_timer_pci, pci, acpi_timer_pci_driver, acpi_timer_pci_devclass, 0, 0); DRIVER_MODULE(acpi_timer_pci, pci, acpi_timer_pci_driver,
acpi_timer_pci_devclass, 0, 0);
/* /*
* Look at PCI devices going past; if we detect one we know contains * Look at PCI devices going past; if we detect one we know contains
@ -375,16 +371,19 @@ acpi_timer_pci_probe(device_t dev)
device = pci_get_device(dev); device = pci_get_device(dev);
revid = pci_get_revid(dev); revid = pci_get_revid(dev);
if (((vendor == 0x8086) && (device == 0x7113) && (revid >= 0x03)) || /* PIIX4M */ /* Detect the PIIX4M and i440MX, respectively */
((vendor == 0x8086) && (device == 0x719b)) || /* i440MX */ if ((vendor == 0x8086 && device == 0x7113 && revid >= 0x03) ||
0) { (vendor == 0x8086 && device == 0x719b)) {
acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount; acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount;
acpi_timer_timecounter.tc_name = "ACPI-fast"; acpi_timer_timecounter.tc_name = "ACPI-fast";
if (bootverbose) if (bootverbose) {
device_printf(acpi_timer_dev, "functional ACPI timer detected, enabling fast timecount interface\n"); device_printf(acpi_timer_dev,"functional ACPI timer detected, "
"enabling fast timecount interface\n");
}
} }
return(ENXIO); /* we never match anything */ /* We never match anything */
return (ENXIO);
} }
#endif #endif

View File

@ -35,41 +35,41 @@
#define ACPIIO_SETSLPSTATE _IOW('P', 3, int) #define ACPIIO_SETSLPSTATE _IOW('P', 3, int)
struct acpi_battdesc { struct acpi_battdesc {
int type; /* battery type: e.g. CMBAT */ int type; /* battery type: e.g. CMBAT */
int phys_unit; /* physical unit of devclass */ int phys_unit; /* physical unit of devclass */
}; };
#define ACPI_BATT_TYPE_CMBAT 0x0000 #define ACPI_BATT_TYPE_CMBAT 0x0000
#define ACPI_BATT_TYPE_SMBAT 0x0001 #define ACPI_BATT_TYPE_SMBAT 0x0001
struct acpi_battinfo { struct acpi_battinfo {
int cap; /* percent */ int cap; /* percent */
int min; /* remianing time */ int min; /* remianing time */
int state; /* battery state */ int state; /* battery state */
}; };
#define ACPI_CMBAT_MAXSTRLEN 32 #define ACPI_CMBAT_MAXSTRLEN 32
struct acpi_bif { struct acpi_bif {
u_int32_t unit; /* 0 for mWh, 1 for mAh */ u_int32_t unit; /* 0 for mWh, 1 for mAh */
u_int32_t dcap; /* Design Capacity */ u_int32_t dcap; /* Design Capacity */
u_int32_t lfcap; /* Last Full capacity */ u_int32_t lfcap; /* Last Full capacity */
u_int32_t btech; /* Battery Technorogy */ u_int32_t btech; /* Battery Technorogy */
u_int32_t dvol; /* Design voltage (mV) */ u_int32_t dvol; /* Design voltage (mV) */
u_int32_t wcap; /* WARN capacity */ u_int32_t wcap; /* WARN capacity */
u_int32_t lcap; /* Low capacity */ u_int32_t lcap; /* Low capacity */
u_int32_t gra1; /* Granulity 1(Warn to Low) */ u_int32_t gra1; /* Granulity 1(Warn to Low) */
u_int32_t gra2; /* Granulity 2(Full to Warn) */ u_int32_t gra2; /* Granulity 2(Full to Warn) */
char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */ char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */
char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */ char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */
char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */ char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */
char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM infomation */ char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM infomation */
}; };
struct acpi_bst { struct acpi_bst {
u_int32_t state; /* Battery State */ u_int32_t state; /* Battery State */
u_int32_t rate; /* Present Rate */ u_int32_t rate; /* Present Rate */
u_int32_t cap; /* Remaining Capacity */ u_int32_t cap; /* Remaining Capacity */
u_int32_t volt; /* Present Voltage */ u_int32_t volt; /* Present Voltage */
}; };
#define ACPI_BATT_STAT_DISCHARG 0x0001 #define ACPI_BATT_STAT_DISCHARG 0x0001
@ -79,28 +79,29 @@ struct acpi_bst {
#define ACPI_BATT_STAT_MAX 0x0007 #define ACPI_BATT_STAT_MAX 0x0007
union acpi_battery_ioctl_arg { union acpi_battery_ioctl_arg {
int unit; /* argument: logical unit (-1 = overall) */ int unit; /* argument: logical unit (-1 = overall) */
struct acpi_battdesc battdesc; struct acpi_battdesc battdesc;
struct acpi_battinfo battinfo; struct acpi_battinfo battinfo;
struct acpi_bif bif; /* for acpi_cmbat */ struct acpi_bif bif; /* for acpi_cmbat */
struct acpi_bst bst; /* for acpi_cmbat */ struct acpi_bst bst; /* for acpi_cmbat */
}; };
/* Common battery ioctl */ /* Common battery ioctl */
#define ACPIIO_BATT_GET_UNITS _IOR('B', 0x01, int) #define ACPIIO_BATT_GET_UNITS _IOR('B', 0x01, int)
#define ACPIIO_BATT_GET_TYPE _IOR('B', 0x02, union acpi_battery_ioctl_arg) #define ACPIIO_BATT_GET_TYPE _IOR('B', 0x02, union acpi_battery_ioctl_arg)
#define ACPIIO_BATT_GET_BATTINFO _IOWR('B', 0x03, union acpi_battery_ioctl_arg) #define ACPIIO_BATT_GET_BATTINFO _IOWR('B', 0x03, union acpi_battery_ioctl_arg)
#define ACPIIO_BATT_GET_BATTDESC _IOWR('B', 0x04, union acpi_battery_ioctl_arg) #define ACPIIO_BATT_GET_BATTDESC _IOWR('B', 0x04, union acpi_battery_ioctl_arg)
/* Cotrol Method battery ioctl */ /* Cotrol Method battery ioctl */
#define ACPIIO_CMBAT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg) #define ACPIIO_CMBAT_GET_BIF _IOWR('B', 0x10, union acpi_battery_ioctl_arg)
#define ACPIIO_CMBAT_GET_BST _IOWR('B', 0x11, union acpi_battery_ioctl_arg) #define ACPIIO_CMBAT_GET_BST _IOWR('B', 0x11, union acpi_battery_ioctl_arg)
#define ACPIIO_ACAD_GET_STATUS _IOR('A', 1, int) #define ACPIIO_ACAD_GET_STATUS _IOR('A', 1, int)
#ifdef _KERNEL #ifdef _KERNEL
extern int acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg); typedef int (*acpi_ioctl_fn)(u_long cmd, caddr_t addr, void *arg);
extern void acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg)); extern int acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg);
extern void acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn);
#endif #endif

View File

@ -142,81 +142,13 @@ struct acpi_device {
#define ACPI_IVAR_MAGIC 0x101 #define ACPI_IVAR_MAGIC 0x101
#define ACPI_IVAR_PRIVATE 0x102 #define ACPI_IVAR_PRIVATE 0x102
static __inline ACPI_HANDLE extern ACPI_HANDLE acpi_get_handle(device_t dev);
acpi_get_handle(device_t dev) extern int acpi_set_handle(device_t dev, ACPI_HANDLE h);
{ extern int acpi_get_magic(device_t dev);
uintptr_t up; extern int acpi_set_magic(device_t dev, int m);
ACPI_HANDLE h; extern void * acpi_get_private(device_t dev);
extern int acpi_set_private(device_t dev, void *p);
if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_HANDLE, &up)) extern ACPI_OBJECT_TYPE acpi_get_type(device_t dev);
return(NULL);
h = (ACPI_HANDLE)up;
return(h);
}
static __inline int
acpi_set_handle(device_t dev, ACPI_HANDLE h)
{
uintptr_t up;
up = (uintptr_t)h;
return(BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_HANDLE, up));
}
static __inline int
acpi_get_magic(device_t dev)
{
uintptr_t up;
int m;
if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_MAGIC, &up))
return(0);
m = (int)up;
return(m);
}
static __inline int
acpi_set_magic(device_t dev, int m)
{
uintptr_t up;
up = (uintptr_t)m;
return(BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_MAGIC, up));
}
static __inline void *
acpi_get_private(device_t dev)
{
uintptr_t up;
void *p;
if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_PRIVATE, &up))
return(NULL);
p = (void *)up;
return(p);
}
static __inline int
acpi_set_private(device_t dev, void *p)
{
uintptr_t up;
up = (uintptr_t)p;
return(BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_PRIVATE, up));
}
static __inline ACPI_OBJECT_TYPE
acpi_get_type(device_t dev)
{
ACPI_HANDLE h;
ACPI_OBJECT_TYPE t;
if ((h = acpi_get_handle(dev)) == NULL)
return(ACPI_TYPE_NOT_FOUND);
if (AcpiGetType(h, &t) != AE_OK)
return(ACPI_TYPE_NOT_FOUND);
return(t);
}
#ifdef ACPI_DEBUGGER #ifdef ACPI_DEBUGGER
extern void acpi_EnterDebugger(void); extern void acpi_EnterDebugger(void);
@ -229,58 +161,67 @@ extern void acpi_EnterDebugger(void);
#define STEP(x) #define STEP(x)
#endif #endif
#define ACPI_VPRINT(dev, acpi_sc, x...) do { \ #define ACPI_VPRINT(dev, acpi_sc, x...) do { \
if (acpi_get_verbose(acpi_sc)) \ if (acpi_get_verbose(acpi_sc)) \
device_printf(dev, x); \ device_printf(dev, x); \
} while (0) } while (0)
#define ACPI_DEVINFO_PRESENT(x) (((x) & 0x9) == 9) #define ACPI_DEVINFO_PRESENT(x) (((x) & 0x9) == 9)
extern BOOLEAN acpi_DeviceIsPresent(device_t dev); extern BOOLEAN acpi_DeviceIsPresent(device_t dev);
extern BOOLEAN acpi_BatteryIsPresent(device_t dev); extern BOOLEAN acpi_BatteryIsPresent(device_t dev);
extern BOOLEAN acpi_MatchHid(device_t dev, char *hid); extern BOOLEAN acpi_MatchHid(device_t dev, char *hid);
extern ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result); extern ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path,
ACPI_HANDLE *result);
extern ACPI_BUFFER *acpi_AllocBuffer(int size); extern ACPI_BUFFER *acpi_AllocBuffer(int size);
extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number); extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path,
extern ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, int *number); int *number);
extern ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp,
int *number);
extern ACPI_STATUS acpi_ForeachPackageObject(ACPI_OBJECT *obj, extern ACPI_STATUS acpi_ForeachPackageObject(ACPI_OBJECT *obj,
void (* func)(ACPI_OBJECT *comp, void *arg), void (*func)(ACPI_OBJECT *comp, void *arg),
void *arg); void *arg);
extern ACPI_STATUS acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp); extern ACPI_STATUS acpi_FindIndexedResource(ACPI_BUFFER *buf, int index,
extern ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res); ACPI_RESOURCE **resp);
extern ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *buf,
ACPI_RESOURCE *res);
extern ACPI_STATUS acpi_SetIntrModel(int model); extern ACPI_STATUS acpi_SetIntrModel(int model);
extern ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); extern ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state);
extern ACPI_STATUS acpi_Enable(struct acpi_softc *sc); extern ACPI_STATUS acpi_Enable(struct acpi_softc *sc);
extern ACPI_STATUS acpi_Disable(struct acpi_softc *sc); extern ACPI_STATUS acpi_Disable(struct acpi_softc *sc);
struct acpi_parse_resource_set { struct acpi_parse_resource_set {
void (* set_init)(device_t dev, void **context); void (*set_init)(device_t dev, void **context);
void (* set_done)(device_t dev, void *context); void (*set_done)(device_t dev, void *context);
void (* set_ioport)(device_t dev, void *context, u_int32_t base, u_int32_t length); void (*set_ioport)(device_t dev, void *context, u_int32_t base,
void (* set_iorange)(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length);
u_int32_t length, u_int32_t align); void (*set_iorange)(device_t dev, void *context,
void (* set_memory)(device_t dev, void *context, u_int32_t base, u_int32_t length); u_int32_t low, u_int32_t high,
void (* set_memoryrange)(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align);
u_int32_t length, u_int32_t align); void (*set_memory)(device_t dev, void *context, u_int32_t base,
void (* set_irq)(device_t dev, void *context, u_int32_t *irq, int cout); u_int32_t length);
void (* set_drq)(device_t dev, void *context, u_int32_t *drq, int count); void (*set_memoryrange)(device_t dev, void *context, u_int32_t low,
void (* set_start_dependant)(device_t dev, void *context, int preference); u_int32_t high, u_int32_t length,
void (* set_end_dependant)(device_t dev, void *context); u_int32_t align);
void (*set_irq)(device_t dev, void *context, u_int32_t *irq,
int cout);
void (*set_drq)(device_t dev, void *context, u_int32_t *drq,
int count);
void (*set_start_dependant)(device_t dev, void *context,
int preference);
void (*set_end_dependant)(device_t dev, void *context);
}; };
extern struct acpi_parse_resource_set acpi_res_parse_set; extern struct acpi_parse_resource_set acpi_res_parse_set;
extern ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle, extern ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
struct acpi_parse_resource_set *set); struct acpi_parse_resource_set *set);
/* XXX until Intel fix this in their headers, based on NEXT_RESOURCE */ /* XXX until Intel fix this in their headers, based on NEXT_RESOURCE */
#define ACPI_RESOURCE_NEXT(Res) (ACPI_RESOURCE *)((UINT8 *) Res + Res->Length) #define ACPI_RESOURCE_NEXT(Res) (ACPI_RESOURCE *)((UINT8 *)Res + Res->Length)
/* /* ACPI event handling */
* ACPI event handling extern UINT32 acpi_eventhandler_power_button_for_sleep(void *context);
*/ extern UINT32 acpi_eventhandler_power_button_for_wakeup(void *context);
extern UINT32 acpi_eventhandler_power_button_for_sleep(void *context); extern UINT32 acpi_eventhandler_sleep_button_for_sleep(void *context);
extern UINT32 acpi_eventhandler_power_button_for_wakeup(void *context); extern UINT32 acpi_eventhandler_sleep_button_for_wakeup(void *context);
extern UINT32 acpi_eventhandler_sleep_button_for_sleep(void *context);
extern UINT32 acpi_eventhandler_sleep_button_for_wakeup(void *context);
#define ACPI_EVENT_PRI_FIRST 0 #define ACPI_EVENT_PRI_FIRST 0
#define ACPI_EVENT_PRI_DEFAULT 10000 #define ACPI_EVENT_PRI_DEFAULT 10000
@ -291,48 +232,40 @@ typedef void (*acpi_event_handler_t)(void *, int);
EVENTHANDLER_DECLARE(acpi_sleep_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_sleep_event, acpi_event_handler_t);
EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t);
/* /* Device power control. */
* Device power control. extern ACPI_STATUS acpi_pwr_switch_consumer(ACPI_HANDLE consumer,
*/ int state);
extern ACPI_STATUS acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state);
/* /* Misc. */
* Misc.
*/
static __inline struct acpi_softc * static __inline struct acpi_softc *
acpi_device_get_parent_softc(device_t child) acpi_device_get_parent_softc(device_t child)
{ {
device_t parent; device_t parent;
parent = device_get_parent(child); parent = device_get_parent(child);
if (parent == NULL) { if (parent == NULL)
return(NULL); return (NULL);
} return (device_get_softc(parent));
return(device_get_softc(parent));
} }
static __inline int static __inline int
acpi_get_verbose(struct acpi_softc *sc) acpi_get_verbose(struct acpi_softc *sc)
{ {
if (sc) if (sc)
return(sc->acpi_verbose); return (sc->acpi_verbose);
return(0); return (0);
} }
extern char *acpi_name(ACPI_HANDLE handle); extern char *acpi_name(ACPI_HANDLE handle);
extern int acpi_avoid(ACPI_HANDLE handle); extern int acpi_avoid(ACPI_HANDLE handle);
extern int acpi_disabled(char *subsys); extern int acpi_disabled(char *subsys);
extern void acpi_device_enable_wake_capability(ACPI_HANDLE h, int enable); extern void acpi_device_enable_wake_capability(ACPI_HANDLE h, int enable);
extern void acpi_device_enable_wake_event(ACPI_HANDLE h); extern void acpi_device_enable_wake_event(ACPI_HANDLE h);
extern int acpi_machdep_init(device_t dev); extern int acpi_machdep_init(device_t dev);
extern void acpi_install_wakeup_handler(struct acpi_softc *sc); extern void acpi_install_wakeup_handler(struct acpi_softc *sc);
extern int acpi_sleep_machdep(struct acpi_softc *sc, int state); extern int acpi_sleep_machdep(struct acpi_softc *sc, int state);
/* /* Battery Abstraction. */
* Battery Abstraction.
*/
struct acpi_battinfo; struct acpi_battinfo;
struct acpi_battdesc; struct acpi_battdesc;
@ -344,15 +277,10 @@ extern int acpi_battery_get_battdesc(int, struct acpi_battdesc *);
extern int acpi_cmbat_get_battinfo(int, struct acpi_battinfo *); extern int acpi_cmbat_get_battinfo(int, struct acpi_battinfo *);
/* /* Embedded controller. */
* Embedded controller.
*/
extern void acpi_ec_ecdt_probe(device_t); extern void acpi_ec_ecdt_probe(device_t);
/* /* AC adapter interface. */
* AC adapter interface.
*/
extern int acpi_acad_get_acline(int *); extern int acpi_acad_get_acline(int *);
#if __FreeBSD_version >= 500000 #if __FreeBSD_version >= 500000
@ -365,9 +293,6 @@ extern int acpi_acad_get_acline(int *);
#endif #endif
#ifdef ACPI_USE_THREADS #ifdef ACPI_USE_THREADS
/* /* ACPI task kernel thread initialization. */
* ACPI task kernel thread initialization.
*/
extern int acpi_task_thread_init(void); extern int acpi_task_thread_init(void);
#endif #endif