acpi_x86.c revision 1.8
1/* $OpenBSD: acpi_x86.c,v 1.8 2022/02/16 06:41:27 deraadt Exp $ */
2/*
3 * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
4 * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/systm.h>
21#include <sys/buf.h>
22#include <sys/device.h>
23#include <sys/malloc.h>
24#include <sys/pool.h>
25#include <sys/fcntl.h>
26#include <sys/ioccom.h>
27#include <sys/event.h>
28#include <sys/signalvar.h>
29#include <sys/proc.h>
30#include <sys/kthread.h>
31#include <sys/sched.h>
32#include <sys/reboot.h>
33#include <sys/sysctl.h>
34#include <sys/mount.h>
35#include <sys/syscallargs.h>
36#include <sys/sensors.h>
37#include <sys/timetc.h>
38
39#ifdef HIBERNATE
40#include <sys/hibernate.h>
41#endif
42
43#include <machine/conf.h>
44#include <machine/cpufunc.h>
45#include <machine/bus.h>
46
47#include <dev/pci/pcivar.h>
48#include <dev/acpi/acpireg.h>
49#include <dev/acpi/acpivar.h>
50#include <dev/acpi/amltypes.h>
51#include <dev/acpi/acpidev.h>
52#include <dev/acpi/dsdt.h>
53
54#include <dev/pci/pcidevs.h>
55#include <dev/pci/ppbreg.h>
56
57#include <dev/pci/pciidevar.h>
58
59#include <machine/apmvar.h>
60#define APMUNIT(dev)	(minor(dev)&0xf0)
61#define APMDEV(dev)	(minor(dev)&0x0f)
62#define APMDEV_NORMAL	0
63#define APMDEV_CTL	8
64
65#include "wd.h"
66#include "softraid.h"
67
68int
69sleep_showstate(void *v, int sleepmode)
70{
71	struct acpi_softc *sc = v;
72
73	switch (sleepmode) {
74	case SLEEP_SUSPEND:
75		sc->sc_state = ACPI_STATE_S3;
76		break;
77	case SLEEP_HIBERNATE:
78		sc->sc_state = ACPI_STATE_S4;
79		break;
80	default:
81		return (EOPNOTSUPP);
82	}
83
84	if (sc->sc_sleeptype[sc->sc_state].slp_typa == -1 ||
85	    sc->sc_sleeptype[sc->sc_state].slp_typb == -1) {
86		printf("%s: state S%d unavailable\n",
87		    sc->sc_dev.dv_xname, sc->sc_state);
88		return (EOPNOTSUPP);
89	}
90
91	/* 1st suspend AML step: _TTS(tostate) */
92	if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
93		return (EINVAL);
94	acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
95	return 0;
96}
97
98int
99sleep_setstate(void *v)
100{
101	struct acpi_softc *sc = v;
102
103	/* 2nd suspend AML step: _PTS(tostate) */
104	if (aml_node_setval(sc, sc->sc_pts, sc->sc_state) != 0)
105		return (EINVAL);
106	acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
107
108	acpibtn_enable_psw();   /* enable _LID for wakeup */
109	acpi_indicator(sc, ACPI_SST_SLEEPING);
110
111	/* 3rd suspend AML step: _GTS(tostate) */
112	aml_node_setval(sc, sc->sc_gts, sc->sc_state);
113	return 0;
114}
115
116int
117gosleep(void *v)
118{
119	struct acpi_softc *sc = v;
120	int ret;
121
122	/* Clear fixed event status */
123	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
124
125	/* Enable wake GPEs */
126	acpi_disable_allgpes(sc);
127	acpi_enable_wakegpes(sc, sc->sc_state);
128
129	ret = acpi_sleep_cpu(sc, sc->sc_state);
130	acpi_resume_cpu(sc, sc->sc_state);
131	sc->sc_state = ACPI_STATE_S0;
132
133	return ret;
134}
135
136void
137sleep_abort(void *v)
138{
139	struct acpi_softc *sc = v;
140
141	sc->sc_state = ACPI_STATE_S0;
142}
143
144int
145sleep_resume(void *v)
146{
147	struct acpi_softc *sc = v;
148
149	acpibtn_disable_psw();		/* disable _LID for wakeup */
150
151	/* 3rd resume AML step: _TTS(runstate) */
152	if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
153		return (EINVAL);
154	acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
155	return 0;
156}
157
158int
159suspend_finish(void *v)
160{
161	struct acpi_softc *sc = v;
162	extern int lid_action;
163
164	acpi_record_event(sc, APM_NORMAL_RESUME);
165	acpi_indicator(sc, ACPI_SST_WORKING);
166
167	/* If we woke up but all the lids are closed, go back to sleep */
168	if (acpibtn_numopenlids() == 0 && lid_action != 0)
169		acpi_addtask(sc, acpi_sleep_task, sc, sc->sc_state);
170	return 0;
171}
172