74
71
return ((BCD >> 4) * 10) + (BCD & 0x0F);
74
/* RTC management helpers */
75
static void get_time (m48t59_t *NVRAM, struct tm *tm)
79
t = time(NULL) + NVRAM->time_offset;
81
memcpy(tm,localtime(&t),sizeof(*tm));
83
localtime_r (&t, tm) ;
87
static void set_time (m48t59_t *NVRAM, struct tm *tm)
91
new_time = mktime(tm);
93
NVRAM->time_offset = new_time - now;
77
96
/* Alarm management */
78
97
static void alarm_cb (void *opaque)
81
100
uint64_t next_time;
82
101
m48t59_t *NVRAM = opaque;
84
qemu_set_irq(NVRAM->IRQ, 1);
85
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
103
pic_set_irq(NVRAM->IRQ, 1);
104
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
86
105
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
87
106
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
88
107
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
89
/* Repeat once a month */
90
qemu_get_timedate(&tm, NVRAM->time_offset);
92
if (tm.tm_mon == 13) {
96
next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
108
/* Repeat once a month */
109
get_time(NVRAM, &tm_now);
110
memcpy(&tm, &tm_now, sizeof(struct tm));
112
if (tm.tm_mon == 13) {
116
next_time = mktime(&tm);
97
117
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
98
118
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
99
119
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
100
120
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
101
/* Repeat once a day */
102
next_time = 24 * 60 * 60;
121
/* Repeat once a day */
122
next_time = 24 * 60 * 60 + mktime(&tm_now);
103
123
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
104
124
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
105
125
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
106
126
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
107
/* Repeat once an hour */
127
/* Repeat once an hour */
128
next_time = 60 * 60 + mktime(&tm_now);
109
129
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
110
130
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
111
131
(NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
112
132
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
113
/* Repeat once a minute */
133
/* Repeat once a minute */
134
next_time = 60 + mktime(&tm_now);
116
/* Repeat once a second */
136
/* Repeat once a second */
137
next_time = 1 + mktime(&tm_now);
119
qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock(vm_clock) +
121
qemu_set_irq(NVRAM->IRQ, 0);
124
static void set_alarm (m48t59_t *NVRAM)
139
qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
140
pic_set_irq(NVRAM->IRQ, 0);
144
static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
147
memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
149
localtime_r (&NVRAM->alarm, tm);
153
static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
155
NVRAM->alarm = mktime(tm);
127
156
if (NVRAM->alrm_timer != NULL) {
128
157
qemu_del_timer(NVRAM->alrm_timer);
129
diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
131
qemu_mod_timer(NVRAM->alrm_timer, diff * 1000);
158
NVRAM->alrm_timer = NULL;
135
/* RTC management helpers */
136
static inline void get_time (m48t59_t *NVRAM, struct tm *tm)
138
qemu_get_timedate(tm, NVRAM->time_offset);
141
static void set_time (m48t59_t *NVRAM, struct tm *tm)
143
NVRAM->time_offset = qemu_timedate_diff(tm);
160
if (NVRAM->alarm - time(NULL) > 0)
161
qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
147
164
/* Watchdog management */
166
183
uint64_t interval; /* in 1/16 seconds */
185
if (NVRAM->wd_timer != NULL) {
186
qemu_del_timer(NVRAM->wd_timer);
187
NVRAM->wd_timer = NULL;
168
189
NVRAM->buffer[0x1FF0] &= ~0x80;
169
if (NVRAM->wd_timer != NULL) {
170
qemu_del_timer(NVRAM->wd_timer);
172
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
173
qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
174
((interval * 1000) >> 4));
191
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
192
qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
193
((interval * 1000) >> 4));
179
197
/* Direct access to NVRAM */
180
void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
198
void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
182
m48t59_t *NVRAM = opaque;
186
203
if (addr > 0x1FF8 && addr < 0x2000)
187
204
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
189
/* check for NVRAM access */
190
if ((NVRAM->type == 2 && addr < 0x7f8) ||
191
(NVRAM->type == 8 && addr < 0x1ff8) ||
192
(NVRAM->type == 59 && addr < 0x1ff0))
205
if (NVRAM->type == 8 &&
206
(addr >= 0x1ff0 && addr <= 0x1ff7))
198
210
/* flags register : read-only */
204
216
/* alarm seconds */
205
217
tmp = fromBCD(val & 0x7F);
206
218
if (tmp >= 0 && tmp <= 59) {
207
NVRAM->alarm.tm_sec = tmp;
219
get_alarm(NVRAM, &tm);
208
221
NVRAM->buffer[0x1FF2] = val;
222
set_alarm(NVRAM, &tm);
213
226
/* alarm minutes */
214
227
tmp = fromBCD(val & 0x7F);
215
228
if (tmp >= 0 && tmp <= 59) {
216
NVRAM->alarm.tm_min = tmp;
229
get_alarm(NVRAM, &tm);
217
231
NVRAM->buffer[0x1FF3] = val;
232
set_alarm(NVRAM, &tm);
222
236
/* alarm hours */
223
237
tmp = fromBCD(val & 0x3F);
224
238
if (tmp >= 0 && tmp <= 23) {
225
NVRAM->alarm.tm_hour = tmp;
239
get_alarm(NVRAM, &tm);
226
241
NVRAM->buffer[0x1FF4] = val;
242
set_alarm(NVRAM, &tm);
232
247
tmp = fromBCD(val & 0x1F);
234
NVRAM->alarm.tm_mday = tmp;
249
get_alarm(NVRAM, &tm);
235
251
NVRAM->buffer[0x1FF5] = val;
252
set_alarm(NVRAM, &tm);
386
389
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
394
395
/* seconds (BCD) */
395
396
get_time(NVRAM, &tm);
396
retval = (NVRAM->buffer[addr] & 0x80) | toBCD(tm.tm_sec);
397
retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
400
400
/* minutes (BCD) */
401
401
get_time(NVRAM, &tm);
402
402
retval = toBCD(tm.tm_min);
406
405
/* hours (BCD) */
407
406
get_time(NVRAM, &tm);
408
407
retval = toBCD(tm.tm_hour);
412
410
/* day of the week / century */
413
411
get_time(NVRAM, &tm);
414
retval = NVRAM->buffer[addr] | tm.tm_wday;
412
retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
419
416
get_time(NVRAM, &tm);
420
417
retval = toBCD(tm.tm_mday);
425
421
get_time(NVRAM, &tm);
426
422
retval = toBCD(tm.tm_mon + 1);
431
426
get_time(NVRAM, &tm);
432
if (NVRAM->type == 8)
427
if (NVRAM->type == 8)
433
428
retval = toBCD(tm.tm_year - 68); // Base year is 1968
435
430
retval = toBCD(tm.tm_year);
449
444
if (addr > 0x1FF9 && addr < 0x2000)
450
NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
445
NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
455
void m48t59_set_addr (void *opaque, uint32_t addr)
450
void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
457
m48t59_t *NVRAM = opaque;
459
452
NVRAM->addr = addr;
462
void m48t59_toggle_lock (void *opaque, int lock)
455
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
464
m48t59_t *NVRAM = opaque;
466
457
NVRAM->lock ^= 1 << lock;
587
static void m48t59_save(QEMUFile *f, void *opaque)
589
m48t59_t *s = opaque;
591
qemu_put_8s(f, &s->lock);
592
qemu_put_be16s(f, &s->addr);
593
qemu_put_buffer(f, s->buffer, s->size);
596
static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
598
m48t59_t *s = opaque;
603
qemu_get_8s(f, &s->lock);
604
qemu_get_be16s(f, &s->addr);
605
qemu_get_buffer(f, s->buffer, s->size);
610
static void m48t59_reset(void *opaque)
612
m48t59_t *NVRAM = opaque;
614
if (NVRAM->alrm_timer != NULL)
615
qemu_del_timer(NVRAM->alrm_timer);
617
if (NVRAM->wd_timer != NULL)
618
qemu_del_timer(NVRAM->wd_timer);
621
578
/* Initialisation routine */
622
m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
579
m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
623
580
uint32_t io_base, uint16_t size,
627
target_phys_addr_t save_base;
629
585
s = qemu_mallocz(sizeof(m48t59_t));
647
603
if (mem_base != 0) {
648
604
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
649
cpu_register_physical_memory(mem_base, size, s->mem_index);
605
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
651
607
if (type == 59) {
652
608
s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
653
609
s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
656
qemu_get_timedate(&s->alarm, 0);
658
qemu_register_reset(m48t59_reset, s);
659
save_base = mem_base ? mem_base : io_base;
660
register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s);