]> Git Repo - qemu.git/blob - hw/mc146818rtc.c
Change MMIO callbacks to use offsets, not absolute addresses.
[qemu.git] / hw / mc146818rtc.c
1 /*
2  * QEMU MC146818 RTC emulation
3  *
4  * Copyright (c) 2003-2004 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "hw.h"
25 #include "qemu-timer.h"
26 #include "sysemu.h"
27 #include "pc.h"
28 #include "isa.h"
29
30 //#define DEBUG_CMOS
31
32 #define RTC_SECONDS             0
33 #define RTC_SECONDS_ALARM       1
34 #define RTC_MINUTES             2
35 #define RTC_MINUTES_ALARM       3
36 #define RTC_HOURS               4
37 #define RTC_HOURS_ALARM         5
38 #define RTC_ALARM_DONT_CARE    0xC0
39
40 #define RTC_DAY_OF_WEEK         6
41 #define RTC_DAY_OF_MONTH        7
42 #define RTC_MONTH               8
43 #define RTC_YEAR                9
44
45 #define RTC_REG_A               10
46 #define RTC_REG_B               11
47 #define RTC_REG_C               12
48 #define RTC_REG_D               13
49
50 #define REG_A_UIP 0x80
51
52 #define REG_B_SET 0x80
53 #define REG_B_PIE 0x40
54 #define REG_B_AIE 0x20
55 #define REG_B_UIE 0x10
56
57 struct RTCState {
58     uint8_t cmos_data[128];
59     uint8_t cmos_index;
60     struct tm current_tm;
61     qemu_irq irq;
62     int it_shift;
63     /* periodic timer */
64     QEMUTimer *periodic_timer;
65     int64_t next_periodic_time;
66     /* second update */
67     int64_t next_second_time;
68     QEMUTimer *second_timer;
69     QEMUTimer *second_timer2;
70 };
71
72 static void rtc_set_time(RTCState *s);
73 static void rtc_copy_date(RTCState *s);
74
75 static void rtc_timer_update(RTCState *s, int64_t current_time)
76 {
77     int period_code, period;
78     int64_t cur_clock, next_irq_clock;
79
80     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
81     if (period_code != 0 &&
82         (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
83         if (period_code <= 2)
84             period_code += 7;
85         /* period in 32 Khz cycles */
86         period = 1 << (period_code - 1);
87         /* compute 32 khz clock */
88         cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
89         next_irq_clock = (cur_clock & ~(period - 1)) + period;
90         s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
91         qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
92     } else {
93         qemu_del_timer(s->periodic_timer);
94     }
95 }
96
97 static void rtc_periodic_timer(void *opaque)
98 {
99     RTCState *s = opaque;
100
101     rtc_timer_update(s, s->next_periodic_time);
102     s->cmos_data[RTC_REG_C] |= 0xc0;
103     qemu_irq_raise(s->irq);
104 }
105
106 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
107 {
108     RTCState *s = opaque;
109
110     if ((addr & 1) == 0) {
111         s->cmos_index = data & 0x7f;
112     } else {
113 #ifdef DEBUG_CMOS
114         printf("cmos: write index=0x%02x val=0x%02x\n",
115                s->cmos_index, data);
116 #endif
117         switch(s->cmos_index) {
118         case RTC_SECONDS_ALARM:
119         case RTC_MINUTES_ALARM:
120         case RTC_HOURS_ALARM:
121             /* XXX: not supported */
122             s->cmos_data[s->cmos_index] = data;
123             break;
124         case RTC_SECONDS:
125         case RTC_MINUTES:
126         case RTC_HOURS:
127         case RTC_DAY_OF_WEEK:
128         case RTC_DAY_OF_MONTH:
129         case RTC_MONTH:
130         case RTC_YEAR:
131             s->cmos_data[s->cmos_index] = data;
132             /* if in set mode, do not update the time */
133             if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
134                 rtc_set_time(s);
135             }
136             break;
137         case RTC_REG_A:
138             /* UIP bit is read only */
139             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
140                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
141             rtc_timer_update(s, qemu_get_clock(vm_clock));
142             break;
143         case RTC_REG_B:
144             if (data & REG_B_SET) {
145                 /* set mode: reset UIP mode */
146                 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
147                 data &= ~REG_B_UIE;
148             } else {
149                 /* if disabling set mode, update the time */
150                 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
151                     rtc_set_time(s);
152                 }
153             }
154             s->cmos_data[RTC_REG_B] = data;
155             rtc_timer_update(s, qemu_get_clock(vm_clock));
156             break;
157         case RTC_REG_C:
158         case RTC_REG_D:
159             /* cannot write to them */
160             break;
161         default:
162             s->cmos_data[s->cmos_index] = data;
163             break;
164         }
165     }
166 }
167
168 static inline int to_bcd(RTCState *s, int a)
169 {
170     if (s->cmos_data[RTC_REG_B] & 0x04) {
171         return a;
172     } else {
173         return ((a / 10) << 4) | (a % 10);
174     }
175 }
176
177 static inline int from_bcd(RTCState *s, int a)
178 {
179     if (s->cmos_data[RTC_REG_B] & 0x04) {
180         return a;
181     } else {
182         return ((a >> 4) * 10) + (a & 0x0f);
183     }
184 }
185
186 static void rtc_set_time(RTCState *s)
187 {
188     struct tm *tm = &s->current_tm;
189
190     tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
191     tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
192     tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
193     if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
194         (s->cmos_data[RTC_HOURS] & 0x80)) {
195         tm->tm_hour += 12;
196     }
197     tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
198     tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
199     tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
200     tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
201 }
202
203 static void rtc_copy_date(RTCState *s)
204 {
205     const struct tm *tm = &s->current_tm;
206
207     s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
208     s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
209     if (s->cmos_data[RTC_REG_B] & 0x02) {
210         /* 24 hour format */
211         s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
212     } else {
213         /* 12 hour format */
214         s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
215         if (tm->tm_hour >= 12)
216             s->cmos_data[RTC_HOURS] |= 0x80;
217     }
218     s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
219     s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
220     s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
221     s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
222 }
223
224 /* month is between 0 and 11. */
225 static int get_days_in_month(int month, int year)
226 {
227     static const int days_tab[12] = {
228         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
229     };
230     int d;
231     if ((unsigned )month >= 12)
232         return 31;
233     d = days_tab[month];
234     if (month == 1) {
235         if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
236             d++;
237     }
238     return d;
239 }
240
241 /* update 'tm' to the next second */
242 static void rtc_next_second(struct tm *tm)
243 {
244     int days_in_month;
245
246     tm->tm_sec++;
247     if ((unsigned)tm->tm_sec >= 60) {
248         tm->tm_sec = 0;
249         tm->tm_min++;
250         if ((unsigned)tm->tm_min >= 60) {
251             tm->tm_min = 0;
252             tm->tm_hour++;
253             if ((unsigned)tm->tm_hour >= 24) {
254                 tm->tm_hour = 0;
255                 /* next day */
256                 tm->tm_wday++;
257                 if ((unsigned)tm->tm_wday >= 7)
258                     tm->tm_wday = 0;
259                 days_in_month = get_days_in_month(tm->tm_mon,
260                                                   tm->tm_year + 1900);
261                 tm->tm_mday++;
262                 if (tm->tm_mday < 1) {
263                     tm->tm_mday = 1;
264                 } else if (tm->tm_mday > days_in_month) {
265                     tm->tm_mday = 1;
266                     tm->tm_mon++;
267                     if (tm->tm_mon >= 12) {
268                         tm->tm_mon = 0;
269                         tm->tm_year++;
270                     }
271                 }
272             }
273         }
274     }
275 }
276
277
278 static void rtc_update_second(void *opaque)
279 {
280     RTCState *s = opaque;
281     int64_t delay;
282
283     /* if the oscillator is not in normal operation, we do not update */
284     if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
285         s->next_second_time += ticks_per_sec;
286         qemu_mod_timer(s->second_timer, s->next_second_time);
287     } else {
288         rtc_next_second(&s->current_tm);
289
290         if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
291             /* update in progress bit */
292             s->cmos_data[RTC_REG_A] |= REG_A_UIP;
293         }
294         /* should be 244 us = 8 / 32768 seconds, but currently the
295            timers do not have the necessary resolution. */
296         delay = (ticks_per_sec * 1) / 100;
297         if (delay < 1)
298             delay = 1;
299         qemu_mod_timer(s->second_timer2,
300                        s->next_second_time + delay);
301     }
302 }
303
304 static void rtc_update_second2(void *opaque)
305 {
306     RTCState *s = opaque;
307
308     if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
309         rtc_copy_date(s);
310     }
311
312     /* check alarm */
313     if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
314         if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
315              s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
316             ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
317              s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
318             ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
319              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
320
321             s->cmos_data[RTC_REG_C] |= 0xa0;
322             qemu_irq_raise(s->irq);
323         }
324     }
325
326     /* update ended interrupt */
327     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
328         s->cmos_data[RTC_REG_C] |= 0x90;
329         qemu_irq_raise(s->irq);
330     }
331
332     /* clear update in progress bit */
333     s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
334
335     s->next_second_time += ticks_per_sec;
336     qemu_mod_timer(s->second_timer, s->next_second_time);
337 }
338
339 static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
340 {
341     RTCState *s = opaque;
342     int ret;
343     if ((addr & 1) == 0) {
344         return 0xff;
345     } else {
346         switch(s->cmos_index) {
347         case RTC_SECONDS:
348         case RTC_MINUTES:
349         case RTC_HOURS:
350         case RTC_DAY_OF_WEEK:
351         case RTC_DAY_OF_MONTH:
352         case RTC_MONTH:
353         case RTC_YEAR:
354             ret = s->cmos_data[s->cmos_index];
355             break;
356         case RTC_REG_A:
357             ret = s->cmos_data[s->cmos_index];
358             break;
359         case RTC_REG_C:
360             ret = s->cmos_data[s->cmos_index];
361             qemu_irq_lower(s->irq);
362             s->cmos_data[RTC_REG_C] = 0x00;
363             break;
364         default:
365             ret = s->cmos_data[s->cmos_index];
366             break;
367         }
368 #ifdef DEBUG_CMOS
369         printf("cmos: read index=0x%02x val=0x%02x\n",
370                s->cmos_index, ret);
371 #endif
372         return ret;
373     }
374 }
375
376 void rtc_set_memory(RTCState *s, int addr, int val)
377 {
378     if (addr >= 0 && addr <= 127)
379         s->cmos_data[addr] = val;
380 }
381
382 void rtc_set_date(RTCState *s, const struct tm *tm)
383 {
384     s->current_tm = *tm;
385     rtc_copy_date(s);
386 }
387
388 /* PC cmos mappings */
389 #define REG_IBM_CENTURY_BYTE        0x32
390 #define REG_IBM_PS2_CENTURY_BYTE    0x37
391
392 static void rtc_set_date_from_host(RTCState *s)
393 {
394     struct tm tm;
395     int val;
396
397     /* set the CMOS date */
398     qemu_get_timedate(&tm, 0);
399     rtc_set_date(s, &tm);
400
401     val = to_bcd(s, (tm.tm_year / 100) + 19);
402     rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
403     rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
404 }
405
406 static void rtc_save(QEMUFile *f, void *opaque)
407 {
408     RTCState *s = opaque;
409
410     qemu_put_buffer(f, s->cmos_data, 128);
411     qemu_put_8s(f, &s->cmos_index);
412
413     qemu_put_be32(f, s->current_tm.tm_sec);
414     qemu_put_be32(f, s->current_tm.tm_min);
415     qemu_put_be32(f, s->current_tm.tm_hour);
416     qemu_put_be32(f, s->current_tm.tm_wday);
417     qemu_put_be32(f, s->current_tm.tm_mday);
418     qemu_put_be32(f, s->current_tm.tm_mon);
419     qemu_put_be32(f, s->current_tm.tm_year);
420
421     qemu_put_timer(f, s->periodic_timer);
422     qemu_put_be64(f, s->next_periodic_time);
423
424     qemu_put_be64(f, s->next_second_time);
425     qemu_put_timer(f, s->second_timer);
426     qemu_put_timer(f, s->second_timer2);
427 }
428
429 static int rtc_load(QEMUFile *f, void *opaque, int version_id)
430 {
431     RTCState *s = opaque;
432
433     if (version_id != 1)
434         return -EINVAL;
435
436     qemu_get_buffer(f, s->cmos_data, 128);
437     qemu_get_8s(f, &s->cmos_index);
438
439     s->current_tm.tm_sec=qemu_get_be32(f);
440     s->current_tm.tm_min=qemu_get_be32(f);
441     s->current_tm.tm_hour=qemu_get_be32(f);
442     s->current_tm.tm_wday=qemu_get_be32(f);
443     s->current_tm.tm_mday=qemu_get_be32(f);
444     s->current_tm.tm_mon=qemu_get_be32(f);
445     s->current_tm.tm_year=qemu_get_be32(f);
446
447     qemu_get_timer(f, s->periodic_timer);
448     s->next_periodic_time=qemu_get_be64(f);
449
450     s->next_second_time=qemu_get_be64(f);
451     qemu_get_timer(f, s->second_timer);
452     qemu_get_timer(f, s->second_timer2);
453     return 0;
454 }
455
456 RTCState *rtc_init(int base, qemu_irq irq)
457 {
458     RTCState *s;
459
460     s = qemu_mallocz(sizeof(RTCState));
461     if (!s)
462         return NULL;
463
464     s->irq = irq;
465     s->cmos_data[RTC_REG_A] = 0x26;
466     s->cmos_data[RTC_REG_B] = 0x02;
467     s->cmos_data[RTC_REG_C] = 0x00;
468     s->cmos_data[RTC_REG_D] = 0x80;
469
470     rtc_set_date_from_host(s);
471
472     s->periodic_timer = qemu_new_timer(vm_clock,
473                                        rtc_periodic_timer, s);
474     s->second_timer = qemu_new_timer(vm_clock,
475                                      rtc_update_second, s);
476     s->second_timer2 = qemu_new_timer(vm_clock,
477                                       rtc_update_second2, s);
478
479     s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
480     qemu_mod_timer(s->second_timer2, s->next_second_time);
481
482     register_ioport_write(base, 2, 1, cmos_ioport_write, s);
483     register_ioport_read(base, 2, 1, cmos_ioport_read, s);
484
485     register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
486     return s;
487 }
488
489 /* Memory mapped interface */
490 static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
491 {
492     RTCState *s = opaque;
493
494     return cmos_ioport_read(s, addr >> s->it_shift) & 0xFF;
495 }
496
497 static void cmos_mm_writeb (void *opaque,
498                             target_phys_addr_t addr, uint32_t value)
499 {
500     RTCState *s = opaque;
501
502     cmos_ioport_write(s, addr >> s->it_shift, value & 0xFF);
503 }
504
505 static uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
506 {
507     RTCState *s = opaque;
508     uint32_t val;
509
510     val = cmos_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
511 #ifdef TARGET_WORDS_BIGENDIAN
512     val = bswap16(val);
513 #endif
514     return val;
515 }
516
517 static void cmos_mm_writew (void *opaque,
518                             target_phys_addr_t addr, uint32_t value)
519 {
520     RTCState *s = opaque;
521 #ifdef TARGET_WORDS_BIGENDIAN
522     value = bswap16(value);
523 #endif
524     cmos_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
525 }
526
527 static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
528 {
529     RTCState *s = opaque;
530     uint32_t val;
531
532     val = cmos_ioport_read(s, addr >> s->it_shift);
533 #ifdef TARGET_WORDS_BIGENDIAN
534     val = bswap32(val);
535 #endif
536     return val;
537 }
538
539 static void cmos_mm_writel (void *opaque,
540                             target_phys_addr_t addr, uint32_t value)
541 {
542     RTCState *s = opaque;
543 #ifdef TARGET_WORDS_BIGENDIAN
544     value = bswap32(value);
545 #endif
546     cmos_ioport_write(s, addr >> s->it_shift, value);
547 }
548
549 static CPUReadMemoryFunc *rtc_mm_read[] = {
550     &cmos_mm_readb,
551     &cmos_mm_readw,
552     &cmos_mm_readl,
553 };
554
555 static CPUWriteMemoryFunc *rtc_mm_write[] = {
556     &cmos_mm_writeb,
557     &cmos_mm_writew,
558     &cmos_mm_writel,
559 };
560
561 RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq)
562 {
563     RTCState *s;
564     int io_memory;
565
566     s = qemu_mallocz(sizeof(RTCState));
567     if (!s)
568         return NULL;
569
570     s->irq = irq;
571     s->cmos_data[RTC_REG_A] = 0x26;
572     s->cmos_data[RTC_REG_B] = 0x02;
573     s->cmos_data[RTC_REG_C] = 0x00;
574     s->cmos_data[RTC_REG_D] = 0x80;
575
576     rtc_set_date_from_host(s);
577
578     s->periodic_timer = qemu_new_timer(vm_clock,
579                                        rtc_periodic_timer, s);
580     s->second_timer = qemu_new_timer(vm_clock,
581                                      rtc_update_second, s);
582     s->second_timer2 = qemu_new_timer(vm_clock,
583                                       rtc_update_second2, s);
584
585     s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
586     qemu_mod_timer(s->second_timer2, s->next_second_time);
587
588     io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
589     cpu_register_physical_memory(base, 2 << it_shift, io_memory);
590
591     register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
592     return s;
593 }
This page took 0.055803 seconds and 4 git commands to generate.