Commit f650305967f3e9a2fe96f59de3062fd9e8b189d0

Authored by balrog
1 parent a0d69e00

Unify RTCs that use host time, fix M48t59 alarm.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3984 c046a42c-6fe2-441c-8c8c-71466251a162
hw/m48t59.c
... ... @@ -53,7 +53,7 @@ struct m48t59_t {
53 53 time_t time_offset;
54 54 time_t stop_time;
55 55 /* Alarm & watchdog */
56   - time_t alarm;
  56 + struct tm alarm;
57 57 struct QEMUTimer *alrm_timer;
58 58 struct QEMUTimer *wd_timer;
59 59 /* NVRAM storage */
... ... @@ -74,35 +74,10 @@ static inline uint8_t fromBCD (uint8_t BCD)
74 74 return ((BCD >> 4) * 10) + (BCD & 0x0F);
75 75 }
76 76  
77   -/* RTC management helpers */
78   -static void get_time (m48t59_t *NVRAM, struct tm *tm)
79   -{
80   - time_t t;
81   -
82   - t = time(NULL) + NVRAM->time_offset;
83   -#ifdef _WIN32
84   - memcpy(tm,localtime(&t),sizeof(*tm));
85   -#else
86   - if (rtc_utc)
87   - gmtime_r (&t, tm);
88   - else
89   - localtime_r (&t, tm) ;
90   -#endif
91   -}
92   -
93   -static void set_time (m48t59_t *NVRAM, struct tm *tm)
94   -{
95   - time_t now, new_time;
96   -
97   - new_time = mktime(tm);
98   - now = time(NULL);
99   - NVRAM->time_offset = new_time - now;
100   -}
101   -
102 77 /* Alarm management */
103 78 static void alarm_cb (void *opaque)
104 79 {
105   - struct tm tm, tm_now;
  80 + struct tm tm;
106 81 uint64_t next_time;
107 82 m48t59_t *NVRAM = opaque;
108 83  
... ... @@ -111,62 +86,62 @@ static void alarm_cb (void *opaque)
111 86 (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
112 87 (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
113 88 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
114   - /* Repeat once a month */
115   - get_time(NVRAM, &tm_now);
116   - memcpy(&tm, &tm_now, sizeof(struct tm));
117   - tm.tm_mon++;
118   - if (tm.tm_mon == 13) {
119   - tm.tm_mon = 1;
120   - tm.tm_year++;
121   - }
122   - next_time = mktime(&tm);
  89 + /* Repeat once a month */
  90 + qemu_get_timedate(&tm, NVRAM->time_offset);
  91 + tm.tm_mon++;
  92 + if (tm.tm_mon == 13) {
  93 + tm.tm_mon = 1;
  94 + tm.tm_year++;
  95 + }
  96 + next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
123 97 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
124 98 (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
125 99 (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
126 100 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
127   - /* Repeat once a day */
128   - next_time = 24 * 60 * 60 + mktime(&tm_now);
  101 + /* Repeat once a day */
  102 + next_time = 24 * 60 * 60;
129 103 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
130 104 (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
131 105 (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
132 106 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
133   - /* Repeat once an hour */
134   - next_time = 60 * 60 + mktime(&tm_now);
  107 + /* Repeat once an hour */
  108 + next_time = 60 * 60;
135 109 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
136 110 (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
137 111 (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
138 112 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
139   - /* Repeat once a minute */
140   - next_time = 60 + mktime(&tm_now);
  113 + /* Repeat once a minute */
  114 + next_time = 60;
141 115 } else {
142   - /* Repeat once a second */
143   - next_time = 1 + mktime(&tm_now);
  116 + /* Repeat once a second */
  117 + next_time = 1;
144 118 }
145   - qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
  119 + qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock(vm_clock) +
  120 + next_time * 1000);
146 121 qemu_set_irq(NVRAM->IRQ, 0);
147 122 }
148 123  
  124 +static void set_alarm (m48t59_t *NVRAM)
  125 +{
  126 + int diff;
  127 + if (NVRAM->alrm_timer != NULL) {
  128 + qemu_del_timer(NVRAM->alrm_timer);
  129 + diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
  130 + if (diff > 0)
  131 + qemu_mod_timer(NVRAM->alrm_timer, diff * 1000);
  132 + }
  133 +}
149 134  
150   -static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
  135 +/* RTC management helpers */
  136 +static inline void get_time (m48t59_t *NVRAM, struct tm *tm)
151 137 {
152   -#ifdef _WIN32
153   - memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
154   -#else
155   - if (rtc_utc)
156   - gmtime_r (&NVRAM->alarm, tm);
157   - else
158   - localtime_r (&NVRAM->alarm, tm);
159   -#endif
  138 + qemu_get_timedate(tm, NVRAM->time_offset);
160 139 }
161 140  
162   -static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
  141 +static void set_time (m48t59_t *NVRAM, struct tm *tm)
163 142 {
164   - NVRAM->alarm = mktime(tm);
165   - if (NVRAM->alrm_timer != NULL) {
166   - qemu_del_timer(NVRAM->alrm_timer);
167   - if (NVRAM->alarm - time(NULL) > 0)
168   - qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
169   - }
  143 + NVRAM->time_offset = qemu_timedate_diff(tm);
  144 + set_alarm(NVRAM);
170 145 }
171 146  
172 147 /* Watchdog management */
... ... @@ -229,40 +204,36 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
229 204 /* alarm seconds */
230 205 tmp = fromBCD(val & 0x7F);
231 206 if (tmp >= 0 && tmp <= 59) {
232   - get_alarm(NVRAM, &tm);
233   - tm.tm_sec = tmp;
  207 + NVRAM->alarm.tm_sec = tmp;
234 208 NVRAM->buffer[0x1FF2] = val;
235   - set_alarm(NVRAM, &tm);
  209 + set_alarm(NVRAM);
236 210 }
237 211 break;
238 212 case 0x1FF3:
239 213 /* alarm minutes */
240 214 tmp = fromBCD(val & 0x7F);
241 215 if (tmp >= 0 && tmp <= 59) {
242   - get_alarm(NVRAM, &tm);
243   - tm.tm_min = tmp;
  216 + NVRAM->alarm.tm_min = tmp;
244 217 NVRAM->buffer[0x1FF3] = val;
245   - set_alarm(NVRAM, &tm);
  218 + set_alarm(NVRAM);
246 219 }
247 220 break;
248 221 case 0x1FF4:
249 222 /* alarm hours */
250 223 tmp = fromBCD(val & 0x3F);
251 224 if (tmp >= 0 && tmp <= 23) {
252   - get_alarm(NVRAM, &tm);
253   - tm.tm_hour = tmp;
  225 + NVRAM->alarm.tm_hour = tmp;
254 226 NVRAM->buffer[0x1FF4] = val;
255   - set_alarm(NVRAM, &tm);
  227 + set_alarm(NVRAM);
256 228 }
257 229 break;
258 230 case 0x1FF5:
259 231 /* alarm date */
260 232 tmp = fromBCD(val & 0x1F);
261 233 if (tmp != 0) {
262   - get_alarm(NVRAM, &tm);
263   - tm.tm_mday = tmp;
  234 + NVRAM->alarm.tm_mday = tmp;
264 235 NVRAM->buffer[0x1FF5] = val;
265   - set_alarm(NVRAM, &tm);
  236 + set_alarm(NVRAM);
266 237 }
267 238 break;
268 239 case 0x1FF6:
... ... @@ -288,7 +259,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
288 259 tm.tm_sec = tmp;
289 260 set_time(NVRAM, &tm);
290 261 }
291   - if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
  262 + if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
292 263 if (val & 0x80) {
293 264 NVRAM->stop_time = time(NULL);
294 265 } else {
... ... @@ -296,7 +267,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
296 267 NVRAM->stop_time = 0;
297 268 }
298 269 }
299   - NVRAM->buffer[addr] = val & 0x80;
  270 + NVRAM->buffer[addr] = val & 0x80;
300 271 break;
301 272 case 0x1FFA:
302 273 case 0x07FA:
... ... @@ -682,6 +653,7 @@ m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
682 653 s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
683 654 }
684 655 s->lock = 0;
  656 + qemu_get_timedate(&s->alarm, 0);
685 657  
686 658 qemu_register_reset(m48t59_reset, s);
687 659 save_base = mem_base ? mem_base : io_base;
... ...
hw/mc146818rtc.c
... ... @@ -392,24 +392,14 @@ void rtc_set_date(RTCState *s, const struct tm *tm)
392 392  
393 393 static void rtc_set_date_from_host(RTCState *s)
394 394 {
395   - time_t ti;
396   - struct tm *tm;
  395 + struct tm tm;
397 396 int val;
398 397  
399 398 /* set the CMOS date */
400   - if (rtc_start_date == -1) {
401   - time(&ti);
402   - if (rtc_utc)
403   - tm = gmtime(&ti);
404   - else
405   - tm = localtime(&ti);
406   - } else {
407   - ti = rtc_start_date;
408   - tm = gmtime(&ti);
409   - }
410   - rtc_set_date(s, tm);
  399 + qemu_get_timedate(&tm, 0);
  400 + rtc_set_date(s, &tm);
411 401  
412   - val = to_bcd(s, (tm->tm_year / 100) + 19);
  402 + val = to_bcd(s, (tm.tm_year / 100) + 19);
413 403 rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
414 404 rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
415 405 }
... ...
hw/omap.c
... ... @@ -4345,7 +4345,6 @@ struct omap_rtc_s {
4345 4345 int pm_am;
4346 4346 int auto_comp;
4347 4347 int round;
4348   - struct tm *(*convert)(const time_t *timep, struct tm *result);
4349 4348 struct tm alarm_tm;
4350 4349 time_t alarm_ti;
4351 4350  
... ... @@ -4668,7 +4667,7 @@ static void omap_rtc_tick(void *opaque)
4668 4667 s->round = 0;
4669 4668 }
4670 4669  
4671   - localtime_r(&s->ti, &s->current_tm);
  4670 + memcpy(&s->current_tm, localtime(&s->ti), sizeof(s->current_tm));
4672 4671  
4673 4672 if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
4674 4673 s->status |= 0x40;
... ... @@ -4719,6 +4718,8 @@ static void omap_rtc_tick(void *opaque)
4719 4718  
4720 4719 static void omap_rtc_reset(struct omap_rtc_s *s)
4721 4720 {
  4721 + struct tm tm;
  4722 +
4722 4723 s->interrupts = 0;
4723 4724 s->comp_reg = 0;
4724 4725 s->running = 0;
... ... @@ -4729,8 +4730,8 @@ static void omap_rtc_reset(struct omap_rtc_s *s)
4729 4730 memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
4730 4731 s->alarm_tm.tm_mday = 0x01;
4731 4732 s->status = 1 << 7;
4732   - time(&s->ti);
4733   - s->ti = mktime(s->convert(&s->ti, &s->current_tm));
  4733 + qemu_get_timedate(&tm, 0);
  4734 + s->ti = mktime(&tm);
4734 4735  
4735 4736 omap_rtc_alarm_update(s);
4736 4737 omap_rtc_tick(s);
... ... @@ -4747,7 +4748,6 @@ struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
4747 4748 s->irq = irq[0];
4748 4749 s->alarm = irq[1];
4749 4750 s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
4750   - s->convert = rtc_utc ? gmtime_r : localtime_r;
4751 4751  
4752 4752 omap_rtc_reset(s);
4753 4753  
... ...
hw/pl031.c
... ... @@ -195,8 +195,7 @@ void pl031_init(uint32_t base, qemu_irq irq)
195 195 {
196 196 int iomemtype;
197 197 pl031_state *s;
198   - time_t ti;
199   - struct tm *tm;
  198 + struct tm tm;
200 199  
201 200 s = qemu_mallocz(sizeof(pl031_state));
202 201 if (!s)
... ... @@ -211,12 +210,8 @@ void pl031_init(uint32_t base, qemu_irq irq)
211 210 s->base = base;
212 211 s->irq = irq;
213 212 /* ??? We assume vm_clock is zero at this point. */
214   - time(&ti);
215   - if (rtc_utc)
216   - tm = gmtime(&ti);
217   - else
218   - tm = localtime(&ti);
219   - s->tick_offset = mktime(tm);
  213 + qemu_get_timedate(&tm, 0);
  214 + s->tick_offset = mktime(&tm);
220 215  
221 216 s->timer = qemu_new_timer(vm_clock, pl031_interrupt, s);
222 217 }
... ...
hw/pxa2xx.c
... ... @@ -1183,27 +1183,22 @@ static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = {
1183 1183  
1184 1184 static void pxa2xx_rtc_init(struct pxa2xx_state_s *s)
1185 1185 {
1186   - struct tm *tm;
1187   - time_t ti;
  1186 + struct tm tm;
1188 1187 int wom;
1189 1188  
1190 1189 s->rttr = 0x7fff;
1191 1190 s->rtsr = 0;
1192 1191  
1193   - time(&ti);
1194   - if (rtc_utc)
1195   - tm = gmtime(&ti);
1196   - else
1197   - tm = localtime(&ti);
1198   - wom = ((tm->tm_mday - 1) / 7) + 1;
1199   -
1200   - s->last_rcnr = (uint32_t) ti;
1201   - s->last_rdcr = (wom << 20) | ((tm->tm_wday + 1) << 17) |
1202   - (tm->tm_hour << 12) | (tm->tm_min << 6) | tm->tm_sec;
1203   - s->last_rycr = ((tm->tm_year + 1900) << 9) |
1204   - ((tm->tm_mon + 1) << 5) | tm->tm_mday;
1205   - s->last_swcr = (tm->tm_hour << 19) |
1206   - (tm->tm_min << 13) | (tm->tm_sec << 7);
  1192 + qemu_get_timedate(&tm, 0);
  1193 + wom = ((tm.tm_mday - 1) / 7) + 1;
  1194 +
  1195 + s->last_rcnr = (uint32_t) mktime(&tm);
  1196 + s->last_rdcr = (wom << 20) | ((tm.tm_wday + 1) << 17) |
  1197 + (tm.tm_hour << 12) | (tm.tm_min << 6) | tm.tm_sec;
  1198 + s->last_rycr = ((tm.tm_year + 1900) << 9) |
  1199 + ((tm.tm_mon + 1) << 5) | tm.tm_mday;
  1200 + s->last_swcr = (tm.tm_hour << 19) |
  1201 + (tm.tm_min << 13) | (tm.tm_sec << 7);
1207 1202 s->last_rtcpicr = 0;
1208 1203 s->last_hz = s->last_sw = s->last_pi = qemu_get_clock(rt_clock);
1209 1204  
... ...
qemu-common.h
... ... @@ -76,6 +76,9 @@ int qemu_bh_poll(void);
76 76  
77 77 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
78 78  
  79 +void qemu_get_timedate(struct tm *tm, int offset);
  80 +int qemu_timedate_diff(struct tm *tm);
  81 +
79 82 /* cutils.c */
80 83 void pstrcpy(char *buf, int buf_size, const char *str);
81 84 char *pstrcat(char *buf, int buf_size, const char *s);
... ...
sysemu.h
... ... @@ -71,8 +71,6 @@ void do_info_slirp(void);
71 71  
72 72 extern int ram_size;
73 73 extern int bios_size;
74   -extern int rtc_utc;
75   -extern int rtc_start_date;
76 74 extern int cirrus_vga_enabled;
77 75 extern int vmsvga_enabled;
78 76 extern int graphic_width;
... ...
... ... @@ -180,8 +180,8 @@ int pit_min_timer_count = 0;
180 180 int nb_nics;
181 181 NICInfo nd_table[MAX_NICS];
182 182 int vm_running;
183   -int rtc_utc = 1;
184   -int rtc_start_date = -1; /* -1 means now */
  183 +static int rtc_utc = 1;
  184 +static int rtc_date_offset = -1; /* -1 means no change */
185 185 int cirrus_vga_enabled = 1;
186 186 int vmsvga_enabled = 0;
187 187 #ifdef TARGET_SPARC
... ... @@ -1565,6 +1565,43 @@ static void quit_timers(void)
1565 1565 }
1566 1566  
1567 1567 /***********************************************************/
  1568 +/* host time/date access */
  1569 +void qemu_get_timedate(struct tm *tm, int offset)
  1570 +{
  1571 + time_t ti;
  1572 + struct tm *ret;
  1573 +
  1574 + time(&ti);
  1575 + ti += offset;
  1576 + if (rtc_date_offset == -1) {
  1577 + if (rtc_utc)
  1578 + ret = gmtime(&ti);
  1579 + else
  1580 + ret = localtime(&ti);
  1581 + } else {
  1582 + ti -= rtc_date_offset;
  1583 + ret = gmtime(&ti);
  1584 + }
  1585 +
  1586 + memcpy(tm, ret, sizeof(struct tm));
  1587 +}
  1588 +
  1589 +int qemu_timedate_diff(struct tm *tm)
  1590 +{
  1591 + time_t seconds;
  1592 +
  1593 + if (rtc_date_offset == -1)
  1594 + if (rtc_utc)
  1595 + seconds = mktimegm(tm);
  1596 + else
  1597 + seconds = mktime(tm);
  1598 + else
  1599 + seconds = mktimegm(tm) + rtc_date_offset;
  1600 +
  1601 + return seconds - time(NULL);
  1602 +}
  1603 +
  1604 +/***********************************************************/
1568 1605 /* character device */
1569 1606  
1570 1607 static void qemu_chr_event(CharDriverState *s, int event)
... ... @@ -8698,8 +8735,9 @@ int main(int argc, char **argv)
8698 8735 case QEMU_OPTION_startdate:
8699 8736 {
8700 8737 struct tm tm;
  8738 + time_t rtc_start_date;
8701 8739 if (!strcmp(optarg, "now")) {
8702   - rtc_start_date = -1;
  8740 + rtc_date_offset = -1;
8703 8741 } else {
8704 8742 if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
8705 8743 &tm.tm_year,
... ... @@ -8728,6 +8766,7 @@ int main(int argc, char **argv)
8728 8766 "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
8729 8767 exit(1);
8730 8768 }
  8769 + rtc_date_offset = time(NULL) - rtc_start_date;
8731 8770 }
8732 8771 }
8733 8772 break;
... ...