xref: /kvmtool/hw/rtc.c (revision 64136c1c52f98d8a2c4960ef7b18efd8b53317d9)
1*64136c1cSPekka Enberg #include "kvm/rtc.h"
2*64136c1cSPekka Enberg 
3*64136c1cSPekka Enberg #include "kvm/ioport.h"
4*64136c1cSPekka Enberg #include "kvm/kvm.h"
5*64136c1cSPekka Enberg 
6*64136c1cSPekka Enberg #include <time.h>
7*64136c1cSPekka Enberg 
8*64136c1cSPekka Enberg static uint8_t cmos_index;
9*64136c1cSPekka Enberg 
10*64136c1cSPekka Enberg #define CMOS_RTC_SECONDS		0x00
11*64136c1cSPekka Enberg #define CMOS_RTC_MINUTES		0x02
12*64136c1cSPekka Enberg #define CMOS_RTC_HOURS			0x04
13*64136c1cSPekka Enberg #define CMOS_RTC_DATE_OF_MONTH		0x07
14*64136c1cSPekka Enberg #define CMOS_RTC_MONTH			0x08
15*64136c1cSPekka Enberg #define CMOS_RTC_YEAR			0x09
16*64136c1cSPekka Enberg 
17*64136c1cSPekka Enberg static inline unsigned char bin2bcd(unsigned val)
18*64136c1cSPekka Enberg {
19*64136c1cSPekka Enberg 	return ((val / 10) << 4) + val % 10;
20*64136c1cSPekka Enberg }
21*64136c1cSPekka Enberg 
22*64136c1cSPekka Enberg static bool cmos_ram_data_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
23*64136c1cSPekka Enberg {
24*64136c1cSPekka Enberg 	struct tm *tm;
25*64136c1cSPekka Enberg 	time_t ti;
26*64136c1cSPekka Enberg 
27*64136c1cSPekka Enberg 	time(&ti);
28*64136c1cSPekka Enberg 
29*64136c1cSPekka Enberg 	tm = gmtime(&ti);
30*64136c1cSPekka Enberg 
31*64136c1cSPekka Enberg 	switch (cmos_index) {
32*64136c1cSPekka Enberg 	case CMOS_RTC_SECONDS:
33*64136c1cSPekka Enberg 		ioport__write8(data, bin2bcd(tm->tm_sec));
34*64136c1cSPekka Enberg 		break;
35*64136c1cSPekka Enberg 	case CMOS_RTC_MINUTES:
36*64136c1cSPekka Enberg 		ioport__write8(data, bin2bcd(tm->tm_min));
37*64136c1cSPekka Enberg 		break;
38*64136c1cSPekka Enberg 	case CMOS_RTC_HOURS:
39*64136c1cSPekka Enberg 		ioport__write8(data, bin2bcd(tm->tm_hour));
40*64136c1cSPekka Enberg 		break;
41*64136c1cSPekka Enberg 	case CMOS_RTC_DATE_OF_MONTH:
42*64136c1cSPekka Enberg 		ioport__write8(data, bin2bcd(tm->tm_mday));
43*64136c1cSPekka Enberg 		break;
44*64136c1cSPekka Enberg 	case CMOS_RTC_MONTH:
45*64136c1cSPekka Enberg 		ioport__write8(data, bin2bcd(tm->tm_mon + 1));
46*64136c1cSPekka Enberg 		break;
47*64136c1cSPekka Enberg 	case CMOS_RTC_YEAR:
48*64136c1cSPekka Enberg 		ioport__write8(data, bin2bcd(tm->tm_year));
49*64136c1cSPekka Enberg 		break;
50*64136c1cSPekka Enberg 	}
51*64136c1cSPekka Enberg 
52*64136c1cSPekka Enberg 	return true;
53*64136c1cSPekka Enberg }
54*64136c1cSPekka Enberg 
55*64136c1cSPekka Enberg static bool cmos_ram_data_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
56*64136c1cSPekka Enberg {
57*64136c1cSPekka Enberg 	return true;
58*64136c1cSPekka Enberg }
59*64136c1cSPekka Enberg 
60*64136c1cSPekka Enberg static struct ioport_operations cmos_ram_data_ioport_ops = {
61*64136c1cSPekka Enberg 	.io_out		= cmos_ram_data_out,
62*64136c1cSPekka Enberg 	.io_in		= cmos_ram_data_in,
63*64136c1cSPekka Enberg };
64*64136c1cSPekka Enberg 
65*64136c1cSPekka Enberg static bool cmos_ram_index_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
66*64136c1cSPekka Enberg {
67*64136c1cSPekka Enberg 	uint8_t value;
68*64136c1cSPekka Enberg 
69*64136c1cSPekka Enberg 	value	= ioport__read8(data);
70*64136c1cSPekka Enberg 
71*64136c1cSPekka Enberg 	self->nmi_disabled	= value & (1UL << 7);
72*64136c1cSPekka Enberg 
73*64136c1cSPekka Enberg 	cmos_index		= value & ~(1UL << 7);
74*64136c1cSPekka Enberg 
75*64136c1cSPekka Enberg 	return true;
76*64136c1cSPekka Enberg }
77*64136c1cSPekka Enberg 
78*64136c1cSPekka Enberg static struct ioport_operations cmos_ram_index_ioport_ops = {
79*64136c1cSPekka Enberg 	.io_out		= cmos_ram_index_out,
80*64136c1cSPekka Enberg };
81*64136c1cSPekka Enberg 
82*64136c1cSPekka Enberg void rtc__init(void)
83*64136c1cSPekka Enberg {
84*64136c1cSPekka Enberg 	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
85*64136c1cSPekka Enberg 	ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1);
86*64136c1cSPekka Enberg 	ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1);
87*64136c1cSPekka Enberg }
88