Revision f6503059

b/hw/m48t59.c
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 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 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 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 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 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 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;
b/hw/mc146818rtc.c
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
}
b/hw/omap.c
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 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 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 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 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

  
b/hw/pl031.c
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 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
}
b/hw/pxa2xx.c
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

  
b/qemu-common.h
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);
b/sysemu.h
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;
b/vl.c
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 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 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 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;

Also available in: Unified diff