Revision f6503059 hw/m48t59.c

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;

Also available in: Unified diff