From owner-acpi-jp@jp.freebsd.org  Thu Aug 24 23:30:59 2000
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id XAA00646;
	Thu, 24 Aug 2000 23:30:59 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from tasogare.imasy.or.jp (daemon@tasogare.imasy.or.jp [202.227.24.5])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id XAA00602
	for <acpi-jp@jp.freebsd.org>; Thu, 24 Aug 2000 23:30:58 +0900 (JST)
	(envelope-from iwasaki@jp.FreeBSD.org)
Received: from localhost (iwasaki.imasy.or.jp [202.227.24.92])
	by tasogare.imasy.or.jp (8.10.2+3.3W/3.7W-tasogare/smtpfeed 1.07) with ESMTP id e7OEUrr08496
	for <acpi-jp@jp.freebsd.org>; Thu, 24 Aug 2000 23:30:53 +0900 (JST)
	(envelope-from iwasaki@jp.FreeBSD.org)
To: acpi-jp@jp.freebsd.org
In-Reply-To: <20000824193334D.iwasaki@jp.FreeBSD.org>
References: <20000824192111I.iwasaki@jp.FreeBSD.org>
	<200008241026.TAA88991@shidahara1.planet.sci.kobe-u.ac.jp>
	<20000824193334D.iwasaki@jp.FreeBSD.org>
X-Mailer: Mew version 1.94.1 on Emacs 19.34 / Mule 2.3 (SUETSUMUHANA)
Mime-Version: 1.0
Content-Type: Text/Plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
Message-Id: <20000824233050Q.iwasaki@jp.FreeBSD.org>
Date: Thu, 24 Aug 2000 23:30:50 +0900
From: Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
X-Dispatcher: imput version 20000228(IM140)
Lines: 518
Reply-To: acpi-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+000315
X-Sequence: acpi-jp 583
Subject: [acpi-jp 583] Re: PowerResource control
Errors-To: owner-acpi-jp@jp.freebsd.org
Sender: owner-acpi-jp@jp.freebsd.org
X-Originator: iwasaki@jp.freebsd.org

> > $B$b$&$=$m$=$m!"(Bacpi.c$B<+BN$bJ,3d$9$kI,MW$,$"$k$G$7$g$&$+$M!#(B
> 
> $B5$$,9g$$$^$9$M!#F1$8$3$H9M$($F$$$^$7$?(B :-)

$B$H$$$&$3$H$G!"(BPowerResource $B$d(B Battery $B$d(B Thermal $B$J$I$NDI2C5!G=$O(B 
acpi_powerres.c $B$_$?$$$K=g<!:n$k$3$H$K$7$F!"(Bacpi.c $B$+$i(B softc $BEy$N(B
$B6&M-$7$?$$$d$D$rDI$$=P$7$F(B acpi.h $B$H$7$F?75,:n@.$7$?$$$H;W$$$^$9!#(B

$B0J2<!"$=$s$J46$8$K$9$k%Q%C%A$H(B shar $B$G$9!#FC$KL5$1$l$PL@F|(B
freefall $B$NJ}$K(B commit $B$7$H$-$^$9!#(B

Index: conf/files
===================================================================
RCS file: /home/cvs/ACPI/sys/conf/files,v
retrieving revision 1.3
diff -u -r1.3 files
--- conf/files	2000/08/05 15:12:30	1.3
+++ conf/files	2000/08/24 14:03:41
@@ -72,6 +72,7 @@
 ddb/db_watch.c		optional ddb
 ddb/db_write_cmd.c	optional ddb
 dev/acpi/acpi.c		count acpi
+dev/acpi/acpi_powerres.c	optional	acpi
 dev/acpi/aml/aml_amlmem.c	optional	acpi
 dev/acpi/aml/aml_common.c	optional	acpi
 dev/acpi/aml/aml_evalobj.c	optional	acpi
Index: dev/acpi/acpi.c
===================================================================
RCS file: /home/cvs/ACPI/sys/dev/acpi/acpi.c,v
retrieving revision 1.26
diff -u -r1.26 acpi.c
--- dev/acpi/acpi.c	2000/08/15 14:43:43	1.26
+++ dev/acpi/acpi.c	2000/08/24 14:03:41
@@ -45,6 +45,8 @@
 
 #include <sys/acpi.h>
 
+#include <dev/acpi/acpi.h>		/* for softc */
+
 #include <dev/acpi/aml/aml_amlmem.h>
 #include <dev/acpi/aml/aml_common.h>
 #include <dev/acpi/aml/aml_env.h>
@@ -85,18 +87,6 @@
 static struct	ACPIaddr acpi_addr;
 struct		ACPIrsdp *acpi_rsdp;
 
-/* softc */
-typedef struct acpi_softc {
-	struct	ACPIsdt *rsdt;
-	struct	ACPIsdt *facp;
-	struct	FACPbody *facp_body;
-	struct	ACPIsdt *dsdt;
-	struct	FACS *facs;
-	int	system_state_initialized;
-	int	broken_wakeuplogic;
-	struct	acpi_system_state_package system_state_package;
-} acpi_softc_t;
-
 /* Character device stuff */
 
 static d_open_t		acpiopen;
@@ -891,6 +881,9 @@
 
 	/* Prepare to sleep */
 	acpi_execute_pts(sc, state);
+
+	/* PowerResource manipulation */
+	acpi_powerres_set_sleeping_state(sc, state);
 
 	if (!sc->system_state_initialized) {
 		return;

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	acpi.h
#	acpi_powerres.c
#
echo x - acpi.h
sed 's/^X//' >acpi.h << 'END-of-acpi.h'
X/*-
X * Copyright (c) 1999 Takanori Watanabe <takawata@shidahara1.planet.sci.kobe-u.ac.jp>
X * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	$FreeBSD$
X */
X
X#ifndef _DEV_ACPI_ACPI_H_
X#define _DEV_ACPI_ACPI_H_
X
X/* PowerResource control */
Xstruct acpi_powerres_device {
X	LIST_ENTRY(acpi_powerres_device) links;
X	struct	aml_name *name;
X	u_int8_t	state;		/* D0 to D3 */
X	u_int8_t	next_state;	/* initialized with D0 */
X};
X
Xstruct acpi_powerres_device_ref {
X	LIST_ENTRY(acpi_powerres_device_ref) links;
X	struct	acpi_powerres_device *device;
X};
X
Xstruct acpi_powerres_info {
X	LIST_ENTRY(acpi_powerres_info) links;
X	struct	aml_name *name;
X	u_int8_t	state;		/* OFF or ON */
X	LIST_HEAD(, acpi_powerres_device_ref) reflist[3]; /* for _PR[0-2] */
X};
X
X/* softc */
Xtypedef struct acpi_softc {
X	struct	ACPIsdt *rsdt;
X	struct	ACPIsdt *facp;
X	struct	FACPbody *facp_body;
X	struct	ACPIsdt *dsdt;
X	struct	FACS *facs;
X	int	system_state_initialized;
X	int	broken_wakeuplogic;
X	struct	acpi_system_state_package system_state_package;
X	LIST_HEAD(, acpi_powerres_info) acpi_powerres_inflist;
X	LIST_HEAD(, acpi_powerres_device) acpi_powerres_devlist;
X} acpi_softc_t;
X
Xvoid acpi_powerres_set_sleeping_state(acpi_softc_t *sc, u_int8_t state);
X
X#endif	/* _DEV_ACPI_ACPI_H_ */
END-of-acpi.h
echo x - acpi_powerres.c
sed 's/^X//' >acpi_powerres.c << 'END-of-acpi_powerres.c'
X/*-
X * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	$FreeBSD$
X */
X
X#include "opt_acpi.h"
X
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/malloc.h>
X
X#include <sys/acpi.h>
X
X#include <dev/acpi/acpi.h>
X
X#include <dev/acpi/aml/aml_amlmem.h>
X#include <dev/acpi/aml/aml_common.h>
X#include <dev/acpi/aml/aml_env.h>
X#include <dev/acpi/aml/aml_evalobj.h>
X#include <dev/acpi/aml/aml_name.h>
X#include <dev/acpi/aml/aml_parse.h>
X#include <dev/acpi/aml/aml_memman.h>
X
Xstatic void acpi_powerres_init(acpi_softc_t *sc);
Xstatic int  acpi_powerres_register(struct aml_name *name, va_list ap);
Xstatic int  acpi_powerres_add_device(struct aml_name *name, va_list ap);
X
Xstatic void
Xacpi_powerres_init(acpi_softc_t *sc)
X{
X	struct	acpi_powerres_info *powerres;
X	struct	acpi_powerres_device_ref *device_ref;
X	struct	acpi_powerres_device *device;
X	int	i;
X
X	while ((powerres = LIST_FIRST(&sc->acpi_powerres_inflist))) {
X#ifdef ACPI_DEBUG
X		printf("acpi_powerres_init:");
X		aml_print_curname(powerres->name);
X		printf("[%d]\n", powerres->state);
X#endif
X		for (i = 0; i < 3; i++) {
X#ifdef ACPI_DEBUG
X			printf("\t_PR%d:", i);
X#endif
X			while ((device_ref = LIST_FIRST(&powerres->reflist[i]))) {
X#ifdef ACPI_DEBUG
X				device = device_ref->device;
X				aml_print_curname(device->name);
X				printf("[%d] ", device->state);
X#endif
X				LIST_REMOVE(device_ref, links);
X				FREE(device_ref, M_TEMP);
X			}
X#ifdef ACPI_DEBUG
X			printf("\n");
X#endif
X			LIST_INIT(&powerres->reflist[i]);
X		}
X		LIST_REMOVE(powerres, links);
X		FREE(powerres, M_TEMP);
X	}
X	LIST_INIT(&sc->acpi_powerres_inflist);
X
X	while ((device = LIST_FIRST(&sc->acpi_powerres_devlist))) {
X		LIST_REMOVE(device, links);
X		FREE(device, M_TEMP);
X	}
X	LIST_INIT(&sc->acpi_powerres_devlist);
X}
X
Xstatic int
Xacpi_powerres_register(struct aml_name *name, va_list ap)
X{
X	int	i;
X	acpi_softc_t *sc;
X	struct	acpi_powerres_info *powerres;
X	struct	aml_name *method;
X	union	aml_object *ret;
X	struct	aml_environ env;
X
X	sc = va_arg(ap, acpi_softc_t *);
X
X	if (name->property == NULL ||
X	    name->property->type != aml_t_powerres) {
X		return (0);
X	}
X
X	MALLOC(powerres, struct acpi_powerres_info *,
X	    sizeof(*powerres), M_TEMP, M_NOWAIT);
X	if (powerres == NULL) {
X		return (1);
X	}
X
X	powerres->name = name;
X
X	/* get the current ON or OFF status for the power resource */
X	method = aml_find_from_namespace(name, "_STA");
X	if (method != NULL) {
X		bzero(&env, sizeof(env));
X		aml_local_stack_push(aml_local_stack_create());
X		ret = aml_eval_name(&env, method);
X		aml_local_stack_delete(aml_local_stack_pop());
X		powerres->state = ret->num.number;	/* OFF or ON */
X	}
X
X	/* XXX must be sorted by resource order of PowerResource */
X	LIST_INSERT_HEAD(&sc->acpi_powerres_inflist, powerres, links);
X
X	for (i = 0; i < 3; i++) {
X		LIST_INIT(&powerres->reflist[i]);
X	}
X
X	return (0);
X}
X
Xstatic int
Xacpi_powerres_add_device(struct aml_name *name, va_list ap)
X{
X	int	i;
X	int	prnum;
X	int	dev_found;
X	acpi_softc_t *sc;
X	struct	acpi_powerres_device *device;
X	struct	acpi_powerres_device_ref *device_ref;
X	struct	acpi_powerres_info *powerres;
X	struct	aml_name *powerres_name;
X	struct	aml_name *method;
X	union	aml_object *ret;
X	struct	aml_environ env;
X
X	sc = va_arg(ap, acpi_softc_t *);
X
X	/* should be _PR[0-2] */
X	prnum =  name->name[3] - '0';
X	if (!(prnum >= 0 && prnum <= 2)) {
X		return (0);
X	}
X
X	if (name->property == NULL ||
X	    name->property->type != aml_t_package) {
X		return (0);
X	}
X
X	if (name->property->package.elements == 0) {
X		return (0);
X	}
X
X	/* make the list of devices */
X	dev_found = 0;
X	LIST_FOREACH(device, &sc->acpi_powerres_devlist, links) {
X		if (device->name == name) {
X			dev_found = 1;
X			break;
X		}
X	}
X	if (!dev_found) {
X		MALLOC(device, struct acpi_powerres_device *,
X		   sizeof(*device), M_TEMP, M_NOWAIT);
X		if (device == NULL) {
X			return (1);
X		}
X
X		/* this is a _PR[0-2] object, we need get a parent of this. */
X		device->name = name->parent;
X		device->state = 0;	/* assume D0 */
X
X		/* get the current device state */
X		method = aml_find_from_namespace(device->name, "_PSC");
X		if (method != NULL) {
X			bzero(&env, sizeof(env));
X			aml_local_stack_push(aml_local_stack_create());
X			ret = aml_eval_name(&env, method);
X			aml_local_stack_delete(aml_local_stack_pop());
X			device->state = ret->num.number;	/* D0 - D3 */
X		}
X		LIST_INSERT_HEAD(&sc->acpi_powerres_devlist, device, links);
X	}
X
X	/* find PowerResource which the device reference to */
X	MALLOC(device_ref, struct acpi_powerres_device_ref *,
X	   sizeof(*device_ref), M_TEMP, M_NOWAIT);
X	if (device_ref == NULL) {
X		return (1);
X	}
X	device_ref->device = device;
X	env.curname = device->name;
X	for (i = 0; i < name->property->package.elements; i++) {
X		if (name->property->package.objects[i]->type != aml_t_namestr) {
X			printf("acpi_powerres_add_device: not name string\n");
X			continue;
X		}
X		powerres_name = aml_search_name(&env,
X		    name->property->package.objects[i]->nstr.dp);
X		if (powerres_name == NULL) {
X			printf("acpi_powerres_add_device: not found\n");
X			continue;
X		}
X
X		LIST_FOREACH(powerres, &sc->acpi_powerres_inflist, links) {
X			if (powerres->name == powerres_name) {
X				LIST_INSERT_HEAD(&powerres->reflist[prnum],
X				    device_ref, links);
X				break;
X			}
X		}
X	}
X
X	return (0);
X}
X
Xvoid
Xacpi_powerres_set_sleeping_state(acpi_softc_t *sc, u_int8_t state)
X{
X	int	i;
X	struct	acpi_powerres_info *powerres;
X	struct	acpi_powerres_device *device;
X	struct	acpi_powerres_device_ref *device_ref;
X	struct	aml_name *method;
X	union	aml_object *ret;
X	struct	aml_environ env;
X
X	if (!(state >= 1 && state <= 4)) {
X		return;
X	}
X
X	acpi_powerres_init(sc);
X	aml_apply_foreach_found_objects(aml_get_rootname(), ".",
X	    acpi_powerres_register, sc);
X	aml_apply_foreach_found_objects(aml_get_rootname(), "_PR",
X	    acpi_powerres_add_device, sc);
X
X	/*
X	 * initialize with D0, then change to D3 later based on
X	 * PowerResource state change.
X	 */
X	LIST_FOREACH(device, &sc->acpi_powerres_devlist, links) {
X		device->next_state = 0;
X	}
X
X	/*
X	 * 7.5.2 System \_Sx state
X	 * Power Resources are in a state compatible with the system Sx
X	 * state.  All power Resources that supply a System Level reference
X	 * of Sn (where n < x) are in the OFF state.
X	 */
X	LIST_FOREACH(powerres, &sc->acpi_powerres_inflist, links) {
X		if (powerres->name->property->pres.level < state) {
X			/* if ON state then put it in the OFF state */
X			if (powerres->state == 1) {
X				method = aml_find_from_namespace(powerres->name,
X				    "_OFF");
X				if (method == NULL) {
X					continue;	/* just in case */
X				}
X
X				bzero(&env, sizeof(env));
X				aml_local_stack_push(aml_local_stack_create());
X				aml_eval_name(&env, method);
X				aml_local_stack_delete(aml_local_stack_pop());
X				powerres->state = 0;
X			}
X			/*
X			 * Device states are compatible with the current
X			 * Power Resource states.
X			 */
X			for (i = 0; i < 3; i++) {
X				LIST_FOREACH(device_ref, &powerres->reflist[i], links) {
X					/* D3 state */
X					device_ref->device->next_state = 3;
X				}
X			}
X		} else {
X			/* if OFF state then put it in the ON state */
X			if (powerres->state == 0) {
X				method = aml_find_from_namespace(powerres->name,
X				    "_ON");
X				if (method == NULL) {
X					continue;	/* just in case */
X				}
X
X				bzero(&env, sizeof(env));
X				aml_local_stack_push(aml_local_stack_create());
X				aml_eval_name(&env, method);
X				aml_local_stack_delete(aml_local_stack_pop());
X				powerres->state = 1;
X			}
X		}
X	}
X
X	/*
X	 * Devices states are compatible with the current Power Resource
X	 * states. only devices which solely reference Power Resources which
X	 * are in the ON state for a given device state can be in that device
X	 * state. In all other cases, the device is in the D3 (off) state.
X	 * Note:
X	 * Or is at least assumed to be in the D3 state by its device driver.
X	 * For example, if the device doesn't explicitly describe how it can
X	 * stay in some state non-off state while the system is in a sleeping
X	 * state, the operating software must assume that the device can lose
X	 * its power and state.
X	 */
X
X	LIST_FOREACH(device, &sc->acpi_powerres_devlist, links) {
X		if (device->next_state == 3 && device->state != 3) {
X			method = aml_find_from_namespace(device->name, "_PS3");
X			if (method != NULL) {
X				bzero(&env, sizeof(env));
X				aml_local_stack_push(aml_local_stack_create());
X				aml_eval_name(&env, method);
X				aml_local_stack_delete(aml_local_stack_pop());
X			}
X		}
X		if (device->next_state == 0 && device->state != 0) {
X			method = aml_find_from_namespace(device->name, "_PS0");
X			if (method != NULL) {
X				bzero(&env, sizeof(env));
X				aml_local_stack_push(aml_local_stack_create());
X				aml_eval_name(&env, method);
X				aml_local_stack_delete(aml_local_stack_pop());
X			}
X		}
X		/* get the current device state */
X		method = aml_find_from_namespace(device->name, "_PSC");
X		if (method != NULL) {
X			bzero(&env, sizeof(env));
X			aml_local_stack_push(aml_local_stack_create());
X			ret = aml_eval_name(&env, method);
X			aml_local_stack_delete(aml_local_stack_pop());
X			device->state = ret->num.number;	/* D0 - D3 */
X		}
X	}
X#if 1
X	acpi_powerres_init(sc);
X#endif
X}
END-of-acpi_powerres.c
exit

