xref: /openbsd-src/sys/arch/loongson/dev/apm.c (revision 8e8b3a2c1cb11722bc4515f4994cf96a3a1cebe7)
1*8e8b3a2cSjsg /*	$OpenBSD: apm.c,v 1.44 2024/05/29 06:39:13 jsg Exp $	*/
213bfa4beSotto 
313bfa4beSotto /*-
413bfa4beSotto  * Copyright (c) 2001 Alexander Guy.  All rights reserved.
513bfa4beSotto  * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved.
613bfa4beSotto  * Copyright (c) 1995 John T. Kohl.  All rights reserved.
713bfa4beSotto  *
813bfa4beSotto  * Redistribution and use in source and binary forms, with or without
913bfa4beSotto  * modification, are permitted provided that the following conditions
1013bfa4beSotto  * are met:
1113bfa4beSotto  * 1. Redistributions of source code must retain the above copyright
1213bfa4beSotto  *    notice, this list of conditions and the following disclaimer.
1313bfa4beSotto  * 2. Redistributions in binary form must reproduce the above copyright
1413bfa4beSotto  *    notice, this list of conditions and the following disclaimer in the
1513bfa4beSotto  *    documentation and/or other materials provided with the distribution.
1613bfa4beSotto  * 3. Neither the names of the authors nor the names of contributors
1713bfa4beSotto  *    may be used to endorse or promote products derived from this software
1813bfa4beSotto  *    without specific prior written permission.
1913bfa4beSotto  *
2013bfa4beSotto  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
2113bfa4beSotto  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2213bfa4beSotto  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2313bfa4beSotto  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
2413bfa4beSotto  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2513bfa4beSotto  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2613bfa4beSotto  * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2713bfa4beSotto  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2813bfa4beSotto  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2913bfa4beSotto  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3013bfa4beSotto  * SUCH DAMAGE.
3113bfa4beSotto  *
3213bfa4beSotto  */
3313bfa4beSotto 
3413bfa4beSotto #include "apm.h"
359f315e03Spirofti #include "wsdisplay.h"
3613bfa4beSotto 
3713bfa4beSotto #include <sys/param.h>
3813bfa4beSotto #include <sys/systm.h>
3913bfa4beSotto #include <sys/kernel.h>
4013bfa4beSotto #include <sys/proc.h>
41f124c57cScheloha #include <sys/clockintr.h>
4213bfa4beSotto #include <sys/device.h>
4313bfa4beSotto #include <sys/fcntl.h>
4413bfa4beSotto #include <sys/ioctl.h>
459f315e03Spirofti #include <sys/buf.h>
4613bfa4beSotto #include <sys/event.h>
471e4b376cSderaadt #include <sys/reboot.h>
483fc8f127Spirofti #include <sys/hibernate.h>
4913bfa4beSotto 
5013bfa4beSotto #include <machine/autoconf.h>
5113bfa4beSotto #include <machine/conf.h>
5213bfa4beSotto #include <machine/cpu.h>
5313bfa4beSotto #include <machine/apmvar.h>
5413bfa4beSotto 
55c16e7cd6Spirofti #include <dev/pci/pcivar.h>    /* pci_dopm */
56c16e7cd6Spirofti 
579f315e03Spirofti #include <dev/wscons/wsdisplayvar.h>
589f315e03Spirofti 
59bec266e2Spirofti #include <loongson/dev/kb3310var.h>
6013bfa4beSotto 
6113bfa4beSotto #if defined(APMDEBUG)
6213bfa4beSotto #define DPRINTF(x)	printf x
6313bfa4beSotto #else
6413bfa4beSotto #define	DPRINTF(x)	/**/
6513bfa4beSotto #endif
6613bfa4beSotto 
6713bfa4beSotto struct apm_softc {
6813bfa4beSotto 	struct device sc_dev;
6913bfa4beSotto 	struct klist sc_note;
7013bfa4beSotto 	int    sc_flags;
7113bfa4beSotto };
7213bfa4beSotto 
7313bfa4beSotto int apmmatch(struct device *, void *, void *);
7413bfa4beSotto void apmattach(struct device *, struct device *, void *);
7513bfa4beSotto 
76471aeecfSnaddy const struct cfattach apm_ca = {
7713bfa4beSotto 	sizeof(struct apm_softc), apmmatch, apmattach
7813bfa4beSotto };
7913bfa4beSotto 
8013bfa4beSotto struct cfdriver apm_cd = {
8113bfa4beSotto 	NULL, "apm", DV_DULL
8213bfa4beSotto };
8313bfa4beSotto 
8413bfa4beSotto #define	APMUNIT(dev)	(minor(dev)&0xf0)
8513bfa4beSotto #define	APMDEV(dev)	(minor(dev)&0x0f)
8613bfa4beSotto #define APMDEV_NORMAL	0
8713bfa4beSotto #define APMDEV_CTL	8
8813bfa4beSotto 
8913bfa4beSotto void filt_apmrdetach(struct knote *kn);
9013bfa4beSotto int filt_apmread(struct knote *kn, long hint);
9113bfa4beSotto int apmkqfilter(dev_t dev, struct knote *kn);
9213bfa4beSotto int apm_getdefaultinfo(struct apm_power_info *);
9313bfa4beSotto 
943fc8f127Spirofti int apm_suspend(int state);
95bec266e2Spirofti 
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 };
10213bfa4beSotto 
10313bfa4beSotto int (*get_apminfo)(struct apm_power_info *) = apm_getdefaultinfo;
10413bfa4beSotto 
10513bfa4beSotto /*
10613bfa4beSotto  * Flags to control kernel display
10713bfa4beSotto  *	SCFLAG_NOPRINT:		do not output APM power messages due to
10813bfa4beSotto  *				a power change event.
10913bfa4beSotto  *
11013bfa4beSotto  *	SCFLAG_PCTPRINT:	do not output APM power messages due to
11113bfa4beSotto  *				to a power change event unless the battery
11213bfa4beSotto  *				percentage changes.
11313bfa4beSotto  */
11413bfa4beSotto 
11513bfa4beSotto #define SCFLAG_NOPRINT	0x0008000
11613bfa4beSotto #define SCFLAG_PCTPRINT	0x0004000
11713bfa4beSotto #define SCFLAG_PRINT	(SCFLAG_NOPRINT|SCFLAG_PCTPRINT)
11813bfa4beSotto 
11913bfa4beSotto #define	SCFLAG_OREAD 	(1 << 0)
12013bfa4beSotto #define	SCFLAG_OWRITE	(1 << 1)
12113bfa4beSotto #define	SCFLAG_OPEN	(SCFLAG_OREAD|SCFLAG_OWRITE)
12213bfa4beSotto 
12313bfa4beSotto 
12413bfa4beSotto int
apmmatch(struct device * parent,void * match,void * aux)12513bfa4beSotto apmmatch(struct device *parent, void *match, void *aux)
12613bfa4beSotto {
12713bfa4beSotto 	struct mainbus_attach_args *maa = aux;
12813bfa4beSotto 
129d57a735dSmiod 	/*
130d57a735dSmiod 	 * It only makes sense to attach on a 2F system, since 2E do not
131d57a735dSmiod 	 * feature speed throttling, and we do not support 2E-based
132d57a735dSmiod 	 * notebooks yet (assuming there are any).
133d57a735dSmiod 	 */
134d57a735dSmiod 	if (strcmp(maa->maa_name, apm_cd.cd_name) == 0 && loongson_ver == 0x2f)
13513bfa4beSotto 		return (1);
13613bfa4beSotto 	return (0);
13713bfa4beSotto }
13813bfa4beSotto 
13913bfa4beSotto void
apmattach(struct device * parent,struct device * self,void * aux)14013bfa4beSotto apmattach(struct device *parent, struct device *self, void *aux)
14113bfa4beSotto {
142c16e7cd6Spirofti 	/* Enable PCI Power Management. */
143c16e7cd6Spirofti 	pci_dopm = 1;
144c16e7cd6Spirofti 
14513bfa4beSotto 	printf("\n");
14613bfa4beSotto }
14713bfa4beSotto 
14813bfa4beSotto int
apmopen(dev_t dev,int flag,int mode,struct proc * p)14913bfa4beSotto apmopen(dev_t dev, int flag, int mode, struct proc *p)
15013bfa4beSotto {
15113bfa4beSotto 	struct apm_softc *sc;
15213bfa4beSotto 	int error = 0;
15313bfa4beSotto 
15413bfa4beSotto 	/* apm0 only */
15513bfa4beSotto 	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
15613bfa4beSotto 	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
15713bfa4beSotto 		return ENXIO;
15813bfa4beSotto 
15913bfa4beSotto 	DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n",
160552f6074Sguenther 	    APMDEV(dev), p->p_p->ps_pid, flag, mode));
16113bfa4beSotto 
16213bfa4beSotto 	switch (APMDEV(dev)) {
16313bfa4beSotto 	case APMDEV_CTL:
16413bfa4beSotto 		if (!(flag & FWRITE)) {
16513bfa4beSotto 			error = EINVAL;
16613bfa4beSotto 			break;
16713bfa4beSotto 		}
16813bfa4beSotto 		if (sc->sc_flags & SCFLAG_OWRITE) {
16913bfa4beSotto 			error = EBUSY;
17013bfa4beSotto 			break;
17113bfa4beSotto 		}
17213bfa4beSotto 		sc->sc_flags |= SCFLAG_OWRITE;
17313bfa4beSotto 		break;
17413bfa4beSotto 	case APMDEV_NORMAL:
17513bfa4beSotto 		if (!(flag & FREAD) || (flag & FWRITE)) {
17613bfa4beSotto 			error = EINVAL;
17713bfa4beSotto 			break;
17813bfa4beSotto 		}
17913bfa4beSotto 		sc->sc_flags |= SCFLAG_OREAD;
18013bfa4beSotto 		break;
18113bfa4beSotto 	default:
18213bfa4beSotto 		error = ENXIO;
18313bfa4beSotto 		break;
18413bfa4beSotto 	}
18513bfa4beSotto 	return error;
18613bfa4beSotto }
18713bfa4beSotto 
18813bfa4beSotto int
apmclose(dev_t dev,int flag,int mode,struct proc * p)18913bfa4beSotto apmclose(dev_t dev, int flag, int mode, struct proc *p)
19013bfa4beSotto {
19113bfa4beSotto 	struct apm_softc *sc;
19213bfa4beSotto 
19313bfa4beSotto 	/* apm0 only */
19413bfa4beSotto 	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
19513bfa4beSotto 	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
19613bfa4beSotto 		return ENXIO;
19713bfa4beSotto 
198552f6074Sguenther 	DPRINTF(("apmclose: pid %d flag %x mode %x\n",
199552f6074Sguenther 	    p->p_p->ps_pid, flag, mode));
20013bfa4beSotto 
20113bfa4beSotto 	switch (APMDEV(dev)) {
20213bfa4beSotto 	case APMDEV_CTL:
20313bfa4beSotto 		sc->sc_flags &= ~SCFLAG_OWRITE;
20413bfa4beSotto 		break;
20513bfa4beSotto 	case APMDEV_NORMAL:
20613bfa4beSotto 		sc->sc_flags &= ~SCFLAG_OREAD;
20713bfa4beSotto 		break;
20813bfa4beSotto 	}
20913bfa4beSotto 	return 0;
21013bfa4beSotto }
21113bfa4beSotto 
21213bfa4beSotto int
apmioctl(dev_t dev,u_long cmd,caddr_t data,int flag,struct proc * p)21313bfa4beSotto apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
21413bfa4beSotto {
21513bfa4beSotto 	struct apm_softc *sc;
21613bfa4beSotto 	struct apm_power_info *power;
21713bfa4beSotto 	int error = 0;
21813bfa4beSotto 
21913bfa4beSotto 	/* apm0 only */
22013bfa4beSotto 	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
22113bfa4beSotto 	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
22213bfa4beSotto 		return ENXIO;
22313bfa4beSotto 
22413bfa4beSotto 	switch (cmd) {
22513bfa4beSotto 		/* some ioctl names from linux */
22613bfa4beSotto 	case APM_IOC_STANDBY:
2277001b0e9Smiod 	case APM_IOC_STANDBY_REQ:
2288f0abd29Spirofti 	case APM_IOC_SUSPEND:
2298f0abd29Spirofti 	case APM_IOC_SUSPEND_REQ:
23013bfa4beSotto 		if ((flag & FWRITE) == 0)
23113bfa4beSotto 			error = EBADF;
2323fc8f127Spirofti 		else if (sys_platform->suspend == NULL ||
2333fc8f127Spirofti 		    sys_platform->resume == NULL)
2343fc8f127Spirofti 			error = EOPNOTSUPP;
23513bfa4beSotto 		else
2368f0abd29Spirofti 			error = apm_suspend(APM_IOC_SUSPEND);
23713bfa4beSotto 		break;
2388f0abd29Spirofti #ifdef HIBERNATE
239524e4b65Spirofti 	case APM_IOC_HIBERNATE:
24013bfa4beSotto 		if ((flag & FWRITE) == 0)
24113bfa4beSotto 			error = EBADF;
242bec266e2Spirofti 		else if (sys_platform->suspend == NULL ||
243bec266e2Spirofti 		    sys_platform->resume == NULL)
244bec266e2Spirofti 			error = EOPNOTSUPP;
2457001b0e9Smiod 		else
2468f0abd29Spirofti 			error = apm_suspend(APM_IOC_HIBERNATE);
24713bfa4beSotto 		break;
2488f0abd29Spirofti #endif
24913bfa4beSotto 	case APM_IOC_PRN_CTL:
25013bfa4beSotto 		if ((flag & FWRITE) == 0)
25113bfa4beSotto 			error = EBADF;
25213bfa4beSotto 		else {
25313bfa4beSotto 			int flag = *(int *)data;
25413bfa4beSotto 			DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag ));
25513bfa4beSotto 			switch (flag) {
25613bfa4beSotto 			case APM_PRINT_ON:	/* enable printing */
25713bfa4beSotto 				sc->sc_flags &= ~SCFLAG_PRINT;
25813bfa4beSotto 				break;
25913bfa4beSotto 			case APM_PRINT_OFF: /* disable printing */
26013bfa4beSotto 				sc->sc_flags &= ~SCFLAG_PRINT;
26113bfa4beSotto 				sc->sc_flags |= SCFLAG_NOPRINT;
26213bfa4beSotto 				break;
26313bfa4beSotto 			case APM_PRINT_PCT: /* disable some printing */
26413bfa4beSotto 				sc->sc_flags &= ~SCFLAG_PRINT;
26513bfa4beSotto 				sc->sc_flags |= SCFLAG_PCTPRINT;
26613bfa4beSotto 				break;
26713bfa4beSotto 			default:
26813bfa4beSotto 				error = EINVAL;
26913bfa4beSotto 				break;
27013bfa4beSotto 			}
27113bfa4beSotto 		}
27213bfa4beSotto 		break;
27313bfa4beSotto 	case APM_IOC_DEV_CTL:
27413bfa4beSotto 		if ((flag & FWRITE) == 0)
27513bfa4beSotto 			error = EBADF;
27613bfa4beSotto 		else
27713bfa4beSotto 			error = EOPNOTSUPP; /* XXX */
27813bfa4beSotto 		break;
27913bfa4beSotto 	case APM_IOC_GETPOWER:
28013bfa4beSotto 		power = (struct apm_power_info *)data;
28113bfa4beSotto 		error = (*get_apminfo)(power);
28213bfa4beSotto 		break;
28313bfa4beSotto 	default:
28413bfa4beSotto 		error = ENOTTY;
28513bfa4beSotto 	}
28613bfa4beSotto 
28713bfa4beSotto 	return error;
28813bfa4beSotto }
28913bfa4beSotto 
29013bfa4beSotto void
filt_apmrdetach(struct knote * kn)29113bfa4beSotto filt_apmrdetach(struct knote *kn)
29213bfa4beSotto {
29313bfa4beSotto 	struct apm_softc *sc = (struct apm_softc *)kn->kn_hook;
29413bfa4beSotto 
2959b0cf67bSvisa 	klist_remove_locked(&sc->sc_note, kn);
29613bfa4beSotto }
29713bfa4beSotto 
29813bfa4beSotto int
filt_apmread(struct knote * kn,long hint)29913bfa4beSotto filt_apmread(struct knote *kn, long hint)
30013bfa4beSotto {
30113bfa4beSotto 	/* XXX weird kqueue_scan() semantics */
30213bfa4beSotto 	if (hint && !kn->kn_data)
30313bfa4beSotto 		kn->kn_data = (int)hint;
30413bfa4beSotto 
30513bfa4beSotto 	return (1);
30613bfa4beSotto }
30713bfa4beSotto 
30813bfa4beSotto int
apmkqfilter(dev_t dev,struct knote * kn)30913bfa4beSotto apmkqfilter(dev_t dev, struct knote *kn)
31013bfa4beSotto {
31113bfa4beSotto 	struct apm_softc *sc;
31213bfa4beSotto 
31313bfa4beSotto 	/* apm0 only */
31413bfa4beSotto 	if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
31513bfa4beSotto 	    !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
31613bfa4beSotto 		return ENXIO;
31713bfa4beSotto 
31813bfa4beSotto 	switch (kn->kn_filter) {
31913bfa4beSotto 	case EVFILT_READ:
32013bfa4beSotto 		kn->kn_fop = &apmread_filtops;
32113bfa4beSotto 		break;
32213bfa4beSotto 	default:
323b8d5a5fbSnicm 		return (EINVAL);
32413bfa4beSotto 	}
32513bfa4beSotto 
32613bfa4beSotto 	kn->kn_hook = (caddr_t)sc;
3279b0cf67bSvisa 	klist_insert_locked(&sc->sc_note, kn);
32813bfa4beSotto 
32913bfa4beSotto 	return (0);
33013bfa4beSotto }
33113bfa4beSotto 
33213bfa4beSotto int
apm_getdefaultinfo(struct apm_power_info * info)33313bfa4beSotto apm_getdefaultinfo(struct apm_power_info *info)
33413bfa4beSotto {
335ba1e1494Sotto 	info->battery_state = APM_BATT_UNKNOWN;
336ba1e1494Sotto 	info->ac_state = APM_AC_UNKNOWN;
33713bfa4beSotto 	info->battery_life = 0;
338ba1e1494Sotto 	info->minutes_left = -1;
33913bfa4beSotto 	return (0);
34013bfa4beSotto }
34113bfa4beSotto 
34213bfa4beSotto void
apm_setinfohook(int (* hook)(struct apm_power_info *))34313bfa4beSotto apm_setinfohook(int (*hook)(struct apm_power_info *))
34413bfa4beSotto {
34513bfa4beSotto 	get_apminfo = hook;
34613bfa4beSotto }
34713bfa4beSotto 
34813bfa4beSotto int
apm_record_event(u_int event,const char * src,const char * msg)34913bfa4beSotto apm_record_event(u_int event, const char *src, const char *msg)
35013bfa4beSotto {
35113bfa4beSotto 	static int apm_evindex;
35213bfa4beSotto 	struct apm_softc *sc;
35313bfa4beSotto 
35413bfa4beSotto 	/* apm0 only */
35513bfa4beSotto 	if (apm_cd.cd_ndevs == 0 || (sc = apm_cd.cd_devs[0]) == NULL)
35613bfa4beSotto 		return ENXIO;
35713bfa4beSotto 
35813bfa4beSotto 	if ((sc->sc_flags & SCFLAG_NOPRINT) == 0)
35913bfa4beSotto 		printf("%s: %s %s\n", sc->sc_dev.dv_xname, src, msg);
36013bfa4beSotto 
36113bfa4beSotto 	/* skip if no user waiting */
36213bfa4beSotto 	if ((sc->sc_flags & SCFLAG_OPEN) == 0)
36313bfa4beSotto 		return (1);
36413bfa4beSotto 
36513bfa4beSotto 	apm_evindex++;
366c78098b6Svisa 	knote_locked(&sc->sc_note, APM_EVENT_COMPOSE(event, apm_evindex));
36713bfa4beSotto 
36813bfa4beSotto 	return (0);
36913bfa4beSotto }
370bec266e2Spirofti 
371bec266e2Spirofti int
apm_suspend(int state)3723fc8f127Spirofti apm_suspend(int state)
373bec266e2Spirofti {
3747001b0e9Smiod 	int rv;
3757001b0e9Smiod 	int s;
3767001b0e9Smiod 
377b045954eSjsg #if NWSDISPLAY > 0
3789f315e03Spirofti 	wsdisplay_suspend();
3799f315e03Spirofti #endif
3801e2339d4Sderaadt 
381299e2953Snaddy 	stop_periodic_resettodr();
3821e2339d4Sderaadt 	resettodr();
3831e2339d4Sderaadt 
38496f419e1Skettenis 	config_suspend_all(DVACT_QUIESCE);
3856380ca96Smpi 	bufq_quiesce();
3869f315e03Spirofti 
3877001b0e9Smiod 	s = splhigh();
3887001b0e9Smiod 	(void)disableintr();
389ebf20b71Sderaadt 	cold = 2;
390bec266e2Spirofti 
39196f419e1Skettenis 	rv = config_suspend_all(DVACT_SUSPEND);
3921e4b376cSderaadt 
393fbaf4decSderaadt 	suspend_randomness();
394fbaf4decSderaadt 
3953fc8f127Spirofti #ifdef HIBERNATE
3968f0abd29Spirofti 	if (state == APM_IOC_HIBERNATE) {
3973fc8f127Spirofti 		uvm_pmr_zero_everything();
3983fc8f127Spirofti 		if (hibernate_suspend()) {
3993fc8f127Spirofti 			printf("apm: hibernate_suspend failed");
4003fc8f127Spirofti 			uvm_pmr_dirty_everything();
4013fc8f127Spirofti 			return (ECANCELED);
4023fc8f127Spirofti 		}
4033fc8f127Spirofti 	}
4043fc8f127Spirofti #endif
4053fc8f127Spirofti 
406d3a836f3Sderaadt 	/* XXX
407d3a836f3Sderaadt 	 * Flag to disk drivers that they should "power down" the disk
408d3a836f3Sderaadt 	 * when we get to DVACT_POWERDOWN.
409d3a836f3Sderaadt 	 */
4101e4b376cSderaadt 	boothowto |= RB_POWERDOWN;
41196f419e1Skettenis 	config_suspend_all(DVACT_POWERDOWN);
4121e4b376cSderaadt 	boothowto &= ~RB_POWERDOWN;
4131e4b376cSderaadt 
4147001b0e9Smiod 	if (rv == 0) {
4157001b0e9Smiod 		rv = sys_platform->suspend();
4167001b0e9Smiod 		if (rv == 0)
4177001b0e9Smiod 			rv = sys_platform->resume();
418bec266e2Spirofti 	}
419f124c57cScheloha 
4203209772dScheloha 	inittodr(gettime());	/* Move the clock forward */
421f124c57cScheloha 	clockintr_cpu_init(NULL);
422f124c57cScheloha 	clockintr_trigger();
423f124c57cScheloha 
42496f419e1Skettenis 	config_suspend_all(DVACT_RESUME);
425bec266e2Spirofti 
4267001b0e9Smiod 	cold = 0;
4277001b0e9Smiod 	(void)enableintr();
4287001b0e9Smiod 	splx(s);
4299f315e03Spirofti 
43087dd1dd0Sderaadt 	resume_randomness(NULL, 0);	/* force RNG upper level reseed */
4319f315e03Spirofti 	bufq_restart();
43237ecb596Sderaadt 
43396f419e1Skettenis 	config_suspend_all(DVACT_WAKEUP);
43437ecb596Sderaadt 
435299e2953Snaddy 	start_periodic_resettodr();
436299e2953Snaddy 
4379f315e03Spirofti #if NWSDISPLAY > 0
4389f315e03Spirofti 	wsdisplay_resume();
4399f315e03Spirofti #endif
4409f315e03Spirofti 
441fc9b224bSjca 	apm_record_event(APM_NORMAL_RESUME, "System", "resumed from sleep");
442fc9b224bSjca 
4439f315e03Spirofti 	return rv;
444bec266e2Spirofti }
445