xref: /dflybsd-src/sys/platform/pc64/isa/pmtimer.c (revision 2267fd784e8a7d1ca13e6d3541caa91f36c9e9fb)
1c8fe38aeSMatthew Dillon /*-
2c8fe38aeSMatthew Dillon  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
3c8fe38aeSMatthew Dillon  * Copyright (c) 2008 The DragonFly Project.
4c8fe38aeSMatthew Dillon  * All rights reserved.
5c8fe38aeSMatthew Dillon  *
6c8fe38aeSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
7c8fe38aeSMatthew Dillon  * modification, are permitted provided that the following conditions
8c8fe38aeSMatthew Dillon  * are met:
9c8fe38aeSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
10c8fe38aeSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
11c8fe38aeSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
12c8fe38aeSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
13c8fe38aeSMatthew Dillon  *    documentation and/or other materials provided with the distribution.
14c8fe38aeSMatthew Dillon  *
15c8fe38aeSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c8fe38aeSMatthew Dillon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c8fe38aeSMatthew Dillon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c8fe38aeSMatthew Dillon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c8fe38aeSMatthew Dillon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c8fe38aeSMatthew Dillon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c8fe38aeSMatthew Dillon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c8fe38aeSMatthew Dillon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c8fe38aeSMatthew Dillon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c8fe38aeSMatthew Dillon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c8fe38aeSMatthew Dillon  * SUCH DAMAGE.
26c8fe38aeSMatthew Dillon  */
27c8fe38aeSMatthew Dillon 
28c8fe38aeSMatthew Dillon /*
29c8fe38aeSMatthew Dillon  * Timer device driver for power management events.
30c8fe38aeSMatthew Dillon  * The code for suspend/resume is derived from APM device driver.
31c8fe38aeSMatthew Dillon  */
32c8fe38aeSMatthew Dillon 
33c8fe38aeSMatthew Dillon #include <sys/param.h>
34c8fe38aeSMatthew Dillon #include <sys/systm.h>
35c8fe38aeSMatthew Dillon #include <sys/bus.h>
36c8fe38aeSMatthew Dillon #include <sys/kernel.h>
37c8fe38aeSMatthew Dillon #include <sys/syslog.h>
38c8fe38aeSMatthew Dillon #include <sys/thread2.h>
39c8fe38aeSMatthew Dillon #include <machine/clock.h>
40c8fe38aeSMatthew Dillon 
41c8fe38aeSMatthew Dillon #include <bus/isa/isavar.h>
42c8fe38aeSMatthew Dillon 
43c8fe38aeSMatthew Dillon static devclass_t pmtimer_devclass;
44c8fe38aeSMatthew Dillon 
45c8fe38aeSMatthew Dillon /* reject any PnP devices for now */
46c8fe38aeSMatthew Dillon static struct isa_pnp_id pmtimer_ids[] = {
47c8fe38aeSMatthew Dillon 	{0}
48c8fe38aeSMatthew Dillon };
49c8fe38aeSMatthew Dillon 
50c8fe38aeSMatthew Dillon static int
pmtimer_probe(device_t dev)51c8fe38aeSMatthew Dillon pmtimer_probe(device_t dev)
52c8fe38aeSMatthew Dillon {
53c8fe38aeSMatthew Dillon 
54c8fe38aeSMatthew Dillon 	if (ISA_PNP_PROBE(device_get_parent(dev), dev, pmtimer_ids) == ENXIO) {
55c8fe38aeSMatthew Dillon 		return (ENXIO);
56c8fe38aeSMatthew Dillon 	}
57c8fe38aeSMatthew Dillon 
58c8fe38aeSMatthew Dillon 	/* only one instance always */
59c8fe38aeSMatthew Dillon 	return (device_get_unit(dev));
60c8fe38aeSMatthew Dillon }
61c8fe38aeSMatthew Dillon 
62c8fe38aeSMatthew Dillon static struct timeval suspend_time;
63c8fe38aeSMatthew Dillon static struct timeval diff_time;
64c8fe38aeSMatthew Dillon 
65c8fe38aeSMatthew Dillon static int
pmtimer_suspend(device_t dev)66c8fe38aeSMatthew Dillon pmtimer_suspend(device_t dev)
67c8fe38aeSMatthew Dillon {
68c8fe38aeSMatthew Dillon 	crit_enter();
69c8fe38aeSMatthew Dillon 	microtime(&diff_time);
70c8fe38aeSMatthew Dillon 	inittodr(0);
71c8fe38aeSMatthew Dillon 	microtime(&suspend_time);
72c8fe38aeSMatthew Dillon 	timevalsub(&diff_time, &suspend_time);
73c8fe38aeSMatthew Dillon 	crit_exit();
74c8fe38aeSMatthew Dillon 	return (0);
75c8fe38aeSMatthew Dillon }
76c8fe38aeSMatthew Dillon 
77c8fe38aeSMatthew Dillon static int
pmtimer_resume(device_t dev)78c8fe38aeSMatthew Dillon pmtimer_resume(device_t dev)
79c8fe38aeSMatthew Dillon {
80c8fe38aeSMatthew Dillon 	u_int second, minute, hour;
81c8fe38aeSMatthew Dillon 	struct timeval resume_time;
82c8fe38aeSMatthew Dillon 
83c8fe38aeSMatthew Dillon 	/* modified for adjkerntz */
84c8fe38aeSMatthew Dillon 	crit_enter();
85c8fe38aeSMatthew Dillon 	timer_restore();		/* restore the all timers */
86c8fe38aeSMatthew Dillon 	inittodr(0);			/* adjust time to RTC */
87c8fe38aeSMatthew Dillon 	microtime(&resume_time);
88c8fe38aeSMatthew Dillon 
89c8fe38aeSMatthew Dillon 	crit_exit();
90c8fe38aeSMatthew Dillon 	second = resume_time.tv_sec - suspend_time.tv_sec;
91c8fe38aeSMatthew Dillon 	hour = second / 3600;
92c8fe38aeSMatthew Dillon 	second %= 3600;
93c8fe38aeSMatthew Dillon 	minute = second / 60;
94c8fe38aeSMatthew Dillon 	second %= 60;
95c8fe38aeSMatthew Dillon 	log(LOG_NOTICE, "wakeup from sleeping state (slept %02d:%02d:%02d)\n",
96c8fe38aeSMatthew Dillon 		hour, minute, second);
97c8fe38aeSMatthew Dillon 	return (0);
98c8fe38aeSMatthew Dillon }
99c8fe38aeSMatthew Dillon 
100c8fe38aeSMatthew Dillon /*
101c8fe38aeSMatthew Dillon  * Because pmtimer is a static device that always exists under any attached
102c8fe38aeSMatthew Dillon  * isa device, and not scanned by the isa device, we need an identify
103c8fe38aeSMatthew Dillon  * function to install the device.
104c8fe38aeSMatthew Dillon  */
105c8fe38aeSMatthew Dillon static device_method_t pmtimer_methods[] = {
106c8fe38aeSMatthew Dillon 	/* Device interface */
107c8fe38aeSMatthew Dillon 	DEVMETHOD(device_identify,	bus_generic_identify),
108c8fe38aeSMatthew Dillon 	DEVMETHOD(device_probe,		pmtimer_probe),
109c8fe38aeSMatthew Dillon 	DEVMETHOD(device_attach,	bus_generic_attach),
110c8fe38aeSMatthew Dillon 	DEVMETHOD(device_suspend,	pmtimer_suspend),
111c8fe38aeSMatthew Dillon 	DEVMETHOD(device_resume,	pmtimer_resume),
112*d3c9c58eSSascha Wildner 	DEVMETHOD_END
113c8fe38aeSMatthew Dillon };
114c8fe38aeSMatthew Dillon 
115c8fe38aeSMatthew Dillon static driver_t pmtimer_driver = {
116c8fe38aeSMatthew Dillon 	"pmtimer",
117c8fe38aeSMatthew Dillon 	pmtimer_methods,
118c8fe38aeSMatthew Dillon 	1,		/* no softc */
119c8fe38aeSMatthew Dillon };
120c8fe38aeSMatthew Dillon 
121aa2b9d05SSascha Wildner DRIVER_MODULE(pmtimer, isa, pmtimer_driver, pmtimer_devclass, NULL, NULL);
122