diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -717,6 +717,10 @@ if ((error = acpi_machdep_init(dev))) goto out; + /* Initialize power resource subsystem. */ + if ((error = acpi_powerres_init())) + goto out; + /* * Setup our sysctl tree. * diff --git a/sys/dev/acpica/acpi_powerres.c b/sys/dev/acpica/acpi_powerres.c --- a/sys/dev/acpica/acpi_powerres.c +++ b/sys/dev/acpica/acpi_powerres.c @@ -34,6 +34,7 @@ #include #include +#include #include /* @@ -120,6 +121,59 @@ static struct acpi_powerconsumer *acpi_pwr_find_consumer(ACPI_HANDLE consumer); +static int +acpi_powerres_ioctl(u_long cmd, caddr_t addr, void *arg) +{ + struct acpi_pwr_get_d_state_arg *get_d_state_arg; + struct acpi_powerconsumer *pc; + ACPI_STATUS status; + ACPI_HANDLE handle; + int err = ENXIO; + + switch (cmd) { + case ACPIIO_PWR_GET_D_STATE: + get_d_state_arg = arg; + get_d_state_arg->path[sizeof(get_d_state_arg->path) - 1] = '\0'; + status = AcpiGetHandle(ACPI_ROOT_OBJECT, get_d_state_arg->path, + &handle); + if (ACPI_FAILURE(status)) { + err = ENOENT; + break; + } + + ACPI_SERIAL_BEGIN(powerres); + pc = acpi_pwr_find_consumer(handle); + if (pc == NULL) { + err = ENOENT; + ACPI_SERIAL_END(powerres); + break; + } + get_d_state_arg->d_state = pc->ac_state; /* TODO */ + ACPI_SERIAL_END(powerres); + + err = 0; + break; + default: + err = EINVAL; + } + + return (err); +} + +int +acpi_powerres_init(void) +{ + int err = 0; + + ACPI_SERIAL_BEGIN(powerres); + + err = acpi_register_ioctl(ACPIIO_PWR_GET_D_STATE, acpi_powerres_ioctl, + NULL); + + ACPI_SERIAL_END(powerres); + return (err); +} + /* * Register a power resource. * diff --git a/sys/dev/acpica/acpiio.h b/sys/dev/acpica/acpiio.h --- a/sys/dev/acpica/acpiio.h +++ b/sys/dev/acpica/acpiio.h @@ -201,6 +201,15 @@ /* Get AC adapter status. */ #define ACPIIO_ACAD_GET_STATUS _IOR('A', 1, int) +/* Power resource ioctls */ +struct acpi_pwr_get_d_state_arg { + char path[256]; /* in: ACPI namespace path */ + int d_state; /* out: D-state (ACPI_STATE_Dx or + ACPI_STATE_UNKNOWN) */ +}; + +#define ACPIIO_PWR_GET_D_STATE _IOR('R', 1, struct acpi_pwr_get_d_state_arg) + #ifdef _KERNEL typedef int (*acpi_ioctl_fn)(u_long cmd, caddr_t addr, void *arg); extern int acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg); diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -474,6 +474,7 @@ EVENTHANDLER_DECLARE(acpi_pre_dev_resume, acpi_event_handler_t); /* Device power control. */ +int acpi_powerres_init(void); ACPI_STATUS acpi_pwr_wake_enable(ACPI_HANDLE consumer, int enable); ACPI_STATUS acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state); acpi_pwr_for_sleep_t acpi_device_pwr_for_sleep;