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