1 #include "kvm/rtc.h" 2 3 #include "kvm/ioport.h" 4 #include "kvm/kvm.h" 5 6 #include <time.h> 7 8 /* 9 * MC146818 RTC registers 10 */ 11 #define RTC_SECONDS 0x00 12 #define RTC_SECONDS_ALARM 0x01 13 #define RTC_MINUTES 0x02 14 #define RTC_MINUTES_ALARM 0x03 15 #define RTC_HOURS 0x04 16 #define RTC_HOURS_ALARM 0x05 17 #define RTC_DAY_OF_WEEK 0x06 18 #define RTC_DAY_OF_MONTH 0x07 19 #define RTC_MONTH 0x08 20 #define RTC_YEAR 0x09 21 22 #define RTC_REG_A 0x0A 23 #define RTC_REG_B 0x0B 24 #define RTC_REG_C 0x0C 25 #define RTC_REG_D 0x0D 26 27 struct rtc_device { 28 u8 cmos_idx; 29 u8 cmos_data[128]; 30 }; 31 32 static struct rtc_device rtc; 33 34 static inline unsigned char bin2bcd(unsigned val) 35 { 36 return ((val / 10) << 4) + val % 10; 37 } 38 39 static bool cmos_ram_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 40 { 41 struct tm *tm; 42 time_t ti; 43 int year; 44 45 time(&ti); 46 47 tm = gmtime(&ti); 48 49 switch (rtc.cmos_idx) { 50 case RTC_SECONDS: 51 ioport__write8(data, bin2bcd(tm->tm_sec)); 52 break; 53 case RTC_MINUTES: 54 ioport__write8(data, bin2bcd(tm->tm_min)); 55 break; 56 case RTC_HOURS: 57 ioport__write8(data, bin2bcd(tm->tm_hour)); 58 break; 59 case RTC_DAY_OF_WEEK: 60 ioport__write8(data, bin2bcd(tm->tm_wday + 1)); 61 break; 62 case RTC_DAY_OF_MONTH: 63 ioport__write8(data, bin2bcd(tm->tm_mday)); 64 break; 65 case RTC_MONTH: 66 ioport__write8(data, bin2bcd(tm->tm_mon + 1)); 67 break; 68 case RTC_YEAR: 69 /* 70 * The gmtime() function returns time since 1900. The CMOS 71 * standard is time since 2000. If the year is < 100, do 72 * nothing; if it is > 100, subtract 100; this is the best fit 73 * with the twisted CMOS logic. 74 */ 75 year = tm->tm_year; 76 if (year > 99) 77 year -= 100; 78 ioport__write8(data, bin2bcd(year)); 79 break; 80 default: 81 ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]); 82 break; 83 } 84 85 return true; 86 } 87 88 static bool cmos_ram_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 89 { 90 switch (rtc.cmos_idx) { 91 case RTC_REG_C: 92 case RTC_REG_D: 93 /* Read-only */ 94 break; 95 default: 96 rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data); 97 break; 98 } 99 100 return true; 101 } 102 103 static struct ioport_operations cmos_ram_data_ioport_ops = { 104 .io_out = cmos_ram_data_out, 105 .io_in = cmos_ram_data_in, 106 }; 107 108 static bool cmos_ram_index_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 109 { 110 u8 value = ioport__read8(data); 111 112 kvm->nmi_disabled = value & (1UL << 7); 113 rtc.cmos_idx = value & ~(1UL << 7); 114 115 return true; 116 } 117 118 static struct ioport_operations cmos_ram_index_ioport_ops = { 119 .io_out = cmos_ram_index_out, 120 }; 121 122 int rtc__init(struct kvm *kvm) 123 { 124 int r = 0; 125 126 /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ 127 r = ioport__register(kvm, 0x0070, &cmos_ram_index_ioport_ops, 1, NULL); 128 if (r < 0) 129 return r; 130 131 r = ioport__register(kvm, 0x0071, &cmos_ram_data_ioport_ops, 1, NULL); 132 if (r < 0) { 133 ioport__unregister(kvm, 0x0071); 134 return r; 135 } 136 137 return r; 138 } 139 dev_init(rtc__init); 140 141 int rtc__exit(struct kvm *kvm) 142 { 143 /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ 144 ioport__unregister(kvm, 0x0070); 145 ioport__unregister(kvm, 0x0071); 146 147 return 0; 148 } 149 dev_exit(rtc__exit); 150