xref: /openbsd-src/sys/arch/arm64/dev/apm.c (revision a74a190b711f8f8a2cc69e9cc1c5bec1009a1cb1)
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