1*a74a190bSjsg /* $OpenBSD: apm.c,v 1.26 2024/10/30 06:16:27 jsg Exp $ */ 2edbb6e97Sphessler 3edbb6e97Sphessler /*- 4edbb6e97Sphessler * Copyright (c) 2001 Alexander Guy. All rights reserved. 5edbb6e97Sphessler * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. 6edbb6e97Sphessler * Copyright (c) 1995 John T. Kohl. All rights reserved. 7edbb6e97Sphessler * 8edbb6e97Sphessler * Redistribution and use in source and binary forms, with or without 9edbb6e97Sphessler * modification, are permitted provided that the following conditions 10edbb6e97Sphessler * are met: 11edbb6e97Sphessler * 1. Redistributions of source code must retain the above copyright 12edbb6e97Sphessler * notice, this list of conditions and the following disclaimer. 13edbb6e97Sphessler * 2. Redistributions in binary form must reproduce the above copyright 14edbb6e97Sphessler * notice, this list of conditions and the following disclaimer in the 15edbb6e97Sphessler * documentation and/or other materials provided with the distribution. 16edbb6e97Sphessler * 3. Neither the names of the authors nor the names of contributors 17edbb6e97Sphessler * may be used to endorse or promote products derived from this software 18edbb6e97Sphessler * without specific prior written permission. 19edbb6e97Sphessler * 20edbb6e97Sphessler * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 21edbb6e97Sphessler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22edbb6e97Sphessler * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23edbb6e97Sphessler * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 24edbb6e97Sphessler * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25edbb6e97Sphessler * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26edbb6e97Sphessler * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27edbb6e97Sphessler * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28edbb6e97Sphessler * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29edbb6e97Sphessler * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30edbb6e97Sphessler * SUCH DAMAGE. 31edbb6e97Sphessler * 32edbb6e97Sphessler */ 33edbb6e97Sphessler 34edbb6e97Sphessler #include "apm.h" 35edbb6e97Sphessler 36edbb6e97Sphessler #include <sys/param.h> 37edbb6e97Sphessler #include <sys/systm.h> 38edbb6e97Sphessler #include <sys/kernel.h> 39edbb6e97Sphessler #include <sys/proc.h> 40edbb6e97Sphessler #include <sys/device.h> 41edbb6e97Sphessler #include <sys/fcntl.h> 42edbb6e97Sphessler #include <sys/ioctl.h> 43edbb6e97Sphessler #include <sys/event.h> 44edbb6e97Sphessler #include <sys/reboot.h> 45edbb6e97Sphessler #include <sys/hibernate.h> 4600c72810Skettenis #include <sys/task.h> 47edbb6e97Sphessler 48edbb6e97Sphessler #include <machine/conf.h> 49edbb6e97Sphessler #include <machine/cpu.h> 50edbb6e97Sphessler #include <machine/acpiapm.h> 51edbb6e97Sphessler #include <machine/apmvar.h> 52edbb6e97Sphessler 53edbb6e97Sphessler #if defined(APMDEBUG) 54edbb6e97Sphessler #define DPRINTF(x) printf x 55edbb6e97Sphessler #else 56edbb6e97Sphessler #define DPRINTF(x) /**/ 57edbb6e97Sphessler #endif 58edbb6e97Sphessler 5900c72810Skettenis #ifdef SUSPEND 608cae9a59Stobhe struct taskq *sleep_taskq; 6100c72810Skettenis struct task suspend_task; 6200c72810Skettenis void do_suspend(void *); 638cae9a59Stobhe #ifdef HIBERNATE 648cae9a59Stobhe struct task hibernate_task; 658cae9a59Stobhe void do_hibernate(void *); 668cae9a59Stobhe #endif 6700c72810Skettenis #endif 6800c72810Skettenis 69edbb6e97Sphessler struct apm_softc { 70edbb6e97Sphessler struct device sc_dev; 71edbb6e97Sphessler struct klist sc_note; 72edbb6e97Sphessler int sc_flags; 73edbb6e97Sphessler }; 74edbb6e97Sphessler 75edbb6e97Sphessler int apmmatch(struct device *, void *, void *); 76edbb6e97Sphessler void apmattach(struct device *, struct device *, void *); 77edbb6e97Sphessler 789fdf0c62Smpi const struct cfattach apm_ca = { 79edbb6e97Sphessler sizeof(struct apm_softc), apmmatch, apmattach 80edbb6e97Sphessler }; 81edbb6e97Sphessler 82edbb6e97Sphessler struct cfdriver apm_cd = { 83edbb6e97Sphessler NULL, "apm", DV_DULL 84edbb6e97Sphessler }; 85edbb6e97Sphessler 86edbb6e97Sphessler #define APMUNIT(dev) (minor(dev)&0xf0) 87edbb6e97Sphessler #define APMDEV(dev) (minor(dev)&0x0f) 88edbb6e97Sphessler #define APMDEV_NORMAL 0 89edbb6e97Sphessler #define APMDEV_CTL 8 90edbb6e97Sphessler 91edbb6e97Sphessler void filt_apmrdetach(struct knote *kn); 92edbb6e97Sphessler int filt_apmread(struct knote *kn, long hint); 93edbb6e97Sphessler int apmkqfilter(dev_t dev, struct knote *kn); 94edbb6e97Sphessler int apm_getdefaultinfo(struct apm_power_info *); 95edbb6e97Sphessler 9694321eb4Svisa const struct filterops apmread_filtops = { 97b8213689Svisa .f_flags = FILTEROP_ISFD, 9894321eb4Svisa .f_attach = NULL, 9994321eb4Svisa .f_detach = filt_apmrdetach, 10094321eb4Svisa .f_event = filt_apmread, 10194321eb4Svisa }; 102edbb6e97Sphessler 103edbb6e97Sphessler int (*get_apminfo)(struct apm_power_info *) = apm_getdefaultinfo; 104edbb6e97Sphessler 105edbb6e97Sphessler /* 106edbb6e97Sphessler * Flags to control kernel display 107edbb6e97Sphessler * SCFLAG_NOPRINT: do not output APM power messages due to 108edbb6e97Sphessler * a power change event. 109edbb6e97Sphessler * 110edbb6e97Sphessler * SCFLAG_PCTPRINT: do not output APM power messages due to 111edbb6e97Sphessler * to a power change event unless the battery 112edbb6e97Sphessler * percentage changes. 113edbb6e97Sphessler */ 114edbb6e97Sphessler 115edbb6e97Sphessler #define SCFLAG_NOPRINT 0x0008000 116edbb6e97Sphessler #define SCFLAG_PCTPRINT 0x0004000 117edbb6e97Sphessler #define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT) 118edbb6e97Sphessler 119edbb6e97Sphessler #define SCFLAG_OREAD (1 << 0) 120edbb6e97Sphessler #define SCFLAG_OWRITE (1 << 1) 121edbb6e97Sphessler #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) 122edbb6e97Sphessler 123edbb6e97Sphessler 124edbb6e97Sphessler int 125edbb6e97Sphessler apmmatch(struct device *parent, void *match, void *aux) 126edbb6e97Sphessler { 127edbb6e97Sphessler return (1); 128edbb6e97Sphessler } 129edbb6e97Sphessler 130edbb6e97Sphessler void 131edbb6e97Sphessler apmattach(struct device *parent, struct device *self, void *aux) 132edbb6e97Sphessler { 13300c72810Skettenis #ifdef SUSPEND 1348cae9a59Stobhe sleep_taskq = taskq_create("sleep", 1, IPL_NONE, 0); 13500c72810Skettenis task_set(&suspend_task, do_suspend, NULL); 1368cae9a59Stobhe #ifdef HIBERNATE 1378cae9a59Stobhe task_set(&hibernate_task, do_hibernate, NULL); 1388cae9a59Stobhe #endif 13900c72810Skettenis #endif 14000c72810Skettenis 141edbb6e97Sphessler acpiapm_open = apmopen; 142edbb6e97Sphessler acpiapm_close = apmclose; 143edbb6e97Sphessler acpiapm_ioctl = apmioctl; 144edbb6e97Sphessler acpiapm_kqfilter = apmkqfilter; 145edbb6e97Sphessler 146edbb6e97Sphessler printf("\n"); 147edbb6e97Sphessler } 148edbb6e97Sphessler 149edbb6e97Sphessler int 150edbb6e97Sphessler apmopen(dev_t dev, int flag, int mode, struct proc *p) 151edbb6e97Sphessler { 152edbb6e97Sphessler struct apm_softc *sc; 153edbb6e97Sphessler int error = 0; 154edbb6e97Sphessler 155edbb6e97Sphessler /* apm0 only */ 156edbb6e97Sphessler if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || 157edbb6e97Sphessler !(sc = apm_cd.cd_devs[APMUNIT(dev)])) 158edbb6e97Sphessler return ENXIO; 159edbb6e97Sphessler 160edbb6e97Sphessler DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n", 161edbb6e97Sphessler APMDEV(dev), p->p_p->ps_pid, flag, mode)); 162edbb6e97Sphessler 163edbb6e97Sphessler switch (APMDEV(dev)) { 164edbb6e97Sphessler case APMDEV_CTL: 165edbb6e97Sphessler if (!(flag & FWRITE)) { 166edbb6e97Sphessler error = EINVAL; 167edbb6e97Sphessler break; 168edbb6e97Sphessler } 169edbb6e97Sphessler if (sc->sc_flags & SCFLAG_OWRITE) { 170edbb6e97Sphessler error = EBUSY; 171edbb6e97Sphessler break; 172edbb6e97Sphessler } 173edbb6e97Sphessler sc->sc_flags |= SCFLAG_OWRITE; 174edbb6e97Sphessler break; 175edbb6e97Sphessler case APMDEV_NORMAL: 176edbb6e97Sphessler if (!(flag & FREAD) || (flag & FWRITE)) { 177edbb6e97Sphessler error = EINVAL; 178edbb6e97Sphessler break; 179edbb6e97Sphessler } 180edbb6e97Sphessler sc->sc_flags |= SCFLAG_OREAD; 181edbb6e97Sphessler break; 182edbb6e97Sphessler default: 183edbb6e97Sphessler error = ENXIO; 184edbb6e97Sphessler break; 185edbb6e97Sphessler } 186edbb6e97Sphessler return error; 187edbb6e97Sphessler } 188edbb6e97Sphessler 189edbb6e97Sphessler int 190edbb6e97Sphessler apmclose(dev_t dev, int flag, int mode, struct proc *p) 191edbb6e97Sphessler { 192edbb6e97Sphessler struct apm_softc *sc; 193edbb6e97Sphessler 194edbb6e97Sphessler /* apm0 only */ 195edbb6e97Sphessler if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || 196edbb6e97Sphessler !(sc = apm_cd.cd_devs[APMUNIT(dev)])) 197edbb6e97Sphessler return ENXIO; 198edbb6e97Sphessler 199edbb6e97Sphessler DPRINTF(("apmclose: pid %d flag %x mode %x\n", 200edbb6e97Sphessler p->p_p->ps_pid, flag, mode)); 201edbb6e97Sphessler 202edbb6e97Sphessler switch (APMDEV(dev)) { 203edbb6e97Sphessler case APMDEV_CTL: 204edbb6e97Sphessler sc->sc_flags &= ~SCFLAG_OWRITE; 205edbb6e97Sphessler break; 206edbb6e97Sphessler case APMDEV_NORMAL: 207edbb6e97Sphessler sc->sc_flags &= ~SCFLAG_OREAD; 208edbb6e97Sphessler break; 209edbb6e97Sphessler } 210edbb6e97Sphessler return 0; 211edbb6e97Sphessler } 212edbb6e97Sphessler 213edbb6e97Sphessler int 214edbb6e97Sphessler apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 215edbb6e97Sphessler { 216edbb6e97Sphessler struct apm_softc *sc; 217edbb6e97Sphessler struct apm_power_info *power; 218edbb6e97Sphessler int error = 0; 219edbb6e97Sphessler 220edbb6e97Sphessler /* apm0 only */ 221edbb6e97Sphessler if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || 222edbb6e97Sphessler !(sc = apm_cd.cd_devs[APMUNIT(dev)])) 223edbb6e97Sphessler return ENXIO; 224edbb6e97Sphessler 225edbb6e97Sphessler switch (cmd) { 22675403bd4Sderaadt #ifdef SUSPEND 227edbb6e97Sphessler case APM_IOC_STANDBY: 228edbb6e97Sphessler case APM_IOC_SUSPEND: 229b5334482Sderaadt if ((flag & FWRITE) == 0) { 230b5334482Sderaadt error = EBADF; 231b5334482Sderaadt break; 232b5334482Sderaadt } 2338cae9a59Stobhe error = request_sleep(SLEEP_SUSPEND); 234b5334482Sderaadt break; 235edbb6e97Sphessler #ifdef HIBERNATE 236edbb6e97Sphessler case APM_IOC_HIBERNATE: 237b5334482Sderaadt if ((error = suser(p)) != 0) 238edbb6e97Sphessler break; 239b5334482Sderaadt if ((flag & FWRITE) == 0) { 240b5334482Sderaadt error = EBADF; 241b5334482Sderaadt break; 242b5334482Sderaadt } 2438cae9a59Stobhe error = request_sleep(SLEEP_HIBERNATE); 244b5334482Sderaadt break; 245b5334482Sderaadt #endif 24675403bd4Sderaadt #endif 247edbb6e97Sphessler case APM_IOC_PRN_CTL: 248edbb6e97Sphessler if ((flag & FWRITE) == 0) 249edbb6e97Sphessler error = EBADF; 250edbb6e97Sphessler else { 251edbb6e97Sphessler int flag = *(int *)data; 252edbb6e97Sphessler DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag )); 253edbb6e97Sphessler switch (flag) { 254edbb6e97Sphessler case APM_PRINT_ON: /* enable printing */ 255edbb6e97Sphessler sc->sc_flags &= ~SCFLAG_PRINT; 256edbb6e97Sphessler break; 257edbb6e97Sphessler case APM_PRINT_OFF: /* disable printing */ 258edbb6e97Sphessler sc->sc_flags &= ~SCFLAG_PRINT; 259edbb6e97Sphessler sc->sc_flags |= SCFLAG_NOPRINT; 260edbb6e97Sphessler break; 261edbb6e97Sphessler case APM_PRINT_PCT: /* disable some printing */ 262edbb6e97Sphessler sc->sc_flags &= ~SCFLAG_PRINT; 263edbb6e97Sphessler sc->sc_flags |= SCFLAG_PCTPRINT; 264edbb6e97Sphessler break; 265edbb6e97Sphessler default: 266edbb6e97Sphessler error = EINVAL; 267edbb6e97Sphessler break; 268edbb6e97Sphessler } 269edbb6e97Sphessler } 270edbb6e97Sphessler break; 271edbb6e97Sphessler case APM_IOC_GETPOWER: 272edbb6e97Sphessler power = (struct apm_power_info *)data; 273edbb6e97Sphessler error = (*get_apminfo)(power); 274edbb6e97Sphessler break; 275edbb6e97Sphessler default: 276edbb6e97Sphessler error = ENOTTY; 277edbb6e97Sphessler } 278edbb6e97Sphessler 279edbb6e97Sphessler return error; 280edbb6e97Sphessler } 281edbb6e97Sphessler 282edbb6e97Sphessler void 283edbb6e97Sphessler filt_apmrdetach(struct knote *kn) 284edbb6e97Sphessler { 285edbb6e97Sphessler struct apm_softc *sc = (struct apm_softc *)kn->kn_hook; 286edbb6e97Sphessler 2879b0cf67bSvisa klist_remove_locked(&sc->sc_note, kn); 288edbb6e97Sphessler } 289edbb6e97Sphessler 290edbb6e97Sphessler int 291edbb6e97Sphessler filt_apmread(struct knote *kn, long hint) 292edbb6e97Sphessler { 293edbb6e97Sphessler /* XXX weird kqueue_scan() semantics */ 294edbb6e97Sphessler if (hint && !kn->kn_data) 295edbb6e97Sphessler kn->kn_data = (int)hint; 296edbb6e97Sphessler 297edbb6e97Sphessler return (1); 298edbb6e97Sphessler } 299edbb6e97Sphessler 300edbb6e97Sphessler int 301edbb6e97Sphessler apmkqfilter(dev_t dev, struct knote *kn) 302edbb6e97Sphessler { 303edbb6e97Sphessler struct apm_softc *sc; 304edbb6e97Sphessler 305edbb6e97Sphessler /* apm0 only */ 306edbb6e97Sphessler if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || 307edbb6e97Sphessler !(sc = apm_cd.cd_devs[APMUNIT(dev)])) 308edbb6e97Sphessler return ENXIO; 309edbb6e97Sphessler 310edbb6e97Sphessler switch (kn->kn_filter) { 311edbb6e97Sphessler case EVFILT_READ: 312edbb6e97Sphessler kn->kn_fop = &apmread_filtops; 313edbb6e97Sphessler break; 314edbb6e97Sphessler default: 315edbb6e97Sphessler return (EINVAL); 316edbb6e97Sphessler } 317edbb6e97Sphessler 318edbb6e97Sphessler kn->kn_hook = (caddr_t)sc; 3199b0cf67bSvisa klist_insert_locked(&sc->sc_note, kn); 320edbb6e97Sphessler 321edbb6e97Sphessler return (0); 322edbb6e97Sphessler } 323edbb6e97Sphessler 324edbb6e97Sphessler int 325edbb6e97Sphessler apm_getdefaultinfo(struct apm_power_info *info) 326edbb6e97Sphessler { 327edbb6e97Sphessler info->battery_state = APM_BATT_UNKNOWN; 328edbb6e97Sphessler info->ac_state = APM_AC_UNKNOWN; 329edbb6e97Sphessler info->battery_life = 0; 330edbb6e97Sphessler info->minutes_left = -1; 331edbb6e97Sphessler return (0); 332edbb6e97Sphessler } 333edbb6e97Sphessler 334edbb6e97Sphessler void 335edbb6e97Sphessler apm_setinfohook(int (*hook)(struct apm_power_info *)) 336edbb6e97Sphessler { 337edbb6e97Sphessler get_apminfo = hook; 338edbb6e97Sphessler } 339edbb6e97Sphessler 340edbb6e97Sphessler int 341dcc3b629Skettenis apm_record_event(u_int event) 342edbb6e97Sphessler { 343dcc3b629Skettenis struct apm_softc *sc = apm_cd.cd_devs[0]; 344edbb6e97Sphessler static int apm_evindex; 345edbb6e97Sphessler 346edbb6e97Sphessler /* skip if no user waiting */ 347dcc3b629Skettenis if (sc == NULL || (sc->sc_flags & SCFLAG_OPEN) == 0) 348dcc3b629Skettenis return 1; 349edbb6e97Sphessler 350edbb6e97Sphessler apm_evindex++; 351c78098b6Svisa knote_locked(&sc->sc_note, APM_EVENT_COMPOSE(event, apm_evindex)); 352dcc3b629Skettenis return 0; 353edbb6e97Sphessler } 354b5334482Sderaadt 355b5334482Sderaadt #ifdef SUSPEND 356b5334482Sderaadt 35700c72810Skettenis void 35800c72810Skettenis do_suspend(void *v) 35900c72810Skettenis { 36000c72810Skettenis sleep_state(v, SLEEP_SUSPEND); 36100c72810Skettenis } 36200c72810Skettenis 3638cae9a59Stobhe #ifdef HIBERNATE 36400c72810Skettenis void 3658cae9a59Stobhe do_hibernate(void *v) 36600c72810Skettenis { 3678cae9a59Stobhe sleep_state(v, SLEEP_HIBERNATE); 3688cae9a59Stobhe } 3698cae9a59Stobhe #endif 3708cae9a59Stobhe 3718cae9a59Stobhe int 3728cae9a59Stobhe request_sleep(int sleepmode) 3738cae9a59Stobhe { 3748cae9a59Stobhe if (sleep_taskq == NULL) 3758cae9a59Stobhe return EINVAL; 3768cae9a59Stobhe 3778cae9a59Stobhe switch (sleepmode) { 3788cae9a59Stobhe case SLEEP_SUSPEND: 3798cae9a59Stobhe task_add(sleep_taskq, &suspend_task); 3808cae9a59Stobhe break; 3818cae9a59Stobhe #ifdef HIBERNATE 3828cae9a59Stobhe case SLEEP_HIBERNATE: 383*a74a190bSjsg if (get_hibernate_io_function(swdevt[0]) == NULL) 3848cae9a59Stobhe return EOPNOTSUPP; 3858cae9a59Stobhe task_add(sleep_taskq, &hibernate_task); 3868cae9a59Stobhe break; 3878cae9a59Stobhe #endif 3888cae9a59Stobhe } 3898cae9a59Stobhe 3908cae9a59Stobhe return 0; 39100c72810Skettenis } 39200c72810Skettenis 393b5334482Sderaadt #ifdef MULTIPROCESSOR 394b5334482Sderaadt 395b5334482Sderaadt void 396b5334482Sderaadt sleep_mp(void) 397b5334482Sderaadt { 3984002e08dSkettenis CPU_INFO_ITERATOR cii; 3994002e08dSkettenis struct cpu_info *ci; 4004002e08dSkettenis 4014002e08dSkettenis CPU_INFO_FOREACH(cii, ci) { 4024002e08dSkettenis if (CPU_IS_PRIMARY(ci)) 4034002e08dSkettenis continue; 4044002e08dSkettenis arm_send_ipi(ci, ARM_IPI_HALT); 4054002e08dSkettenis while (ci->ci_flags & CPUF_RUNNING) 4064002e08dSkettenis CPU_BUSY_CYCLE(); 4074002e08dSkettenis } 408b5334482Sderaadt } 409b5334482Sderaadt 410b5334482Sderaadt void 411b5334482Sderaadt resume_mp(void) 412b5334482Sderaadt { 4134002e08dSkettenis CPU_INFO_ITERATOR cii; 4144002e08dSkettenis struct cpu_info *ci; 4154002e08dSkettenis 4164002e08dSkettenis CPU_INFO_FOREACH(cii, ci) { 4174002e08dSkettenis if (CPU_IS_PRIMARY(ci)) 4184002e08dSkettenis continue; 4194002e08dSkettenis cpu_resume_secondary(ci); 4204002e08dSkettenis } 4214002e08dSkettenis cpu_boot_secondary_processors(); 422b5334482Sderaadt } 423b5334482Sderaadt 424b5334482Sderaadt #endif /* MULTIPROCESSOR */ 425b5334482Sderaadt 426b5334482Sderaadt int 427b5334482Sderaadt sleep_showstate(void *v, int sleepmode) 428b5334482Sderaadt { 429586aa7dfSkettenis if (sleepmode == SLEEP_SUSPEND) 430b5334482Sderaadt return 0; 4314002e08dSkettenis 4324002e08dSkettenis return EOPNOTSUPP; 433b5334482Sderaadt } 434b5334482Sderaadt 435b5334482Sderaadt int 436b5334482Sderaadt sleep_setstate(void *v) 437b5334482Sderaadt { 438b5334482Sderaadt return 0; 439b5334482Sderaadt } 440b5334482Sderaadt 4414a9a38d5Sderaadt int 442b5334482Sderaadt gosleep(void *v) 443b5334482Sderaadt { 4444002e08dSkettenis return cpu_suspend_primary(); 445b5334482Sderaadt } 446b5334482Sderaadt 447b5334482Sderaadt int 448b5334482Sderaadt sleep_resume(void *v) 449b5334482Sderaadt { 450b5334482Sderaadt return 0; 451b5334482Sderaadt } 452b5334482Sderaadt 4534a9a38d5Sderaadt int 454b5334482Sderaadt suspend_finish(void *v) 455b5334482Sderaadt { 456dcc3b629Skettenis apm_record_event(APM_NORMAL_RESUME); 4574a9a38d5Sderaadt return 0; 458b5334482Sderaadt } 459b5334482Sderaadt 460b5334482Sderaadt #endif /* SUSPEND */ 461