Make debug printing consistent (Robert Reif)
[qemu] / hw / m48t59.c
1 /*
2  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
3  *
4  * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
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 "nvram.h"
26 #include "isa.h"
27 #include "qemu-timer.h"
28 #include "sysemu.h"
29
30 //#define DEBUG_NVRAM
31
32 #if defined(DEBUG_NVRAM)
33 #define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
34 #else
35 #define NVRAM_PRINTF(fmt, args...) do { } while (0)
36 #endif
37
38 /*
39  * The M48T08 and M48T59 chips are very similar. The newer '59 has
40  * alarm and a watchdog timer and related control registers. In the
41  * PPC platform there is also a nvram lock function.
42  */
43 struct m48t59_t {
44     /* Model parameters */
45     int type; // 8 = m48t08, 59 = m48t59
46     /* Hardware parameters */
47     qemu_irq IRQ;
48     int mem_index;
49     target_phys_addr_t mem_base;
50     uint32_t io_base;
51     uint16_t size;
52     /* RTC management */
53     time_t   time_offset;
54     time_t   stop_time;
55     /* Alarm & watchdog */
56     time_t   alarm;
57     struct QEMUTimer *alrm_timer;
58     struct QEMUTimer *wd_timer;
59     /* NVRAM storage */
60     uint8_t  lock;
61     uint16_t addr;
62     uint8_t *buffer;
63 };
64
65 /* Fake timer functions */
66 /* Generic helpers for BCD */
67 static inline uint8_t toBCD (uint8_t value)
68 {
69     return (((value / 10) % 10) << 4) | (value % 10);
70 }
71
72 static inline uint8_t fromBCD (uint8_t BCD)
73 {
74     return ((BCD >> 4) * 10) + (BCD & 0x0F);
75 }
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 /* Alarm management */
103 static void alarm_cb (void *opaque)
104 {
105     struct tm tm, tm_now;
106     uint64_t next_time;
107     m48t59_t *NVRAM = opaque;
108
109     qemu_set_irq(NVRAM->IRQ, 1);
110     if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
111         (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
112         (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
113         (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);
123     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
124                (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
125                (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
126                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
127         /* Repeat once a day */
128         next_time = 24 * 60 * 60 + mktime(&tm_now);
129     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
130                (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
131                (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
132                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
133         /* Repeat once an hour */
134         next_time = 60 * 60 + mktime(&tm_now);
135     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
136                (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
137                (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
138                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
139         /* Repeat once a minute */
140         next_time = 60 + mktime(&tm_now);
141     } else {
142         /* Repeat once a second */
143         next_time = 1 + mktime(&tm_now);
144     }
145     qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
146     qemu_set_irq(NVRAM->IRQ, 0);
147 }
148
149
150 static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
151 {
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
160 }
161
162 static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
163 {
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     }
170 }
171
172 /* Watchdog management */
173 static void watchdog_cb (void *opaque)
174 {
175     m48t59_t *NVRAM = opaque;
176
177     NVRAM->buffer[0x1FF0] |= 0x80;
178     if (NVRAM->buffer[0x1FF7] & 0x80) {
179         NVRAM->buffer[0x1FF7] = 0x00;
180         NVRAM->buffer[0x1FFC] &= ~0x40;
181         /* May it be a hw CPU Reset instead ? */
182         qemu_system_reset_request();
183     } else {
184         qemu_set_irq(NVRAM->IRQ, 1);
185         qemu_set_irq(NVRAM->IRQ, 0);
186     }
187 }
188
189 static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
190 {
191     uint64_t interval; /* in 1/16 seconds */
192
193     NVRAM->buffer[0x1FF0] &= ~0x80;
194     if (NVRAM->wd_timer != NULL) {
195         qemu_del_timer(NVRAM->wd_timer);
196         if (value != 0) {
197             interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
198             qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
199                            ((interval * 1000) >> 4));
200         }
201     }
202 }
203
204 /* Direct access to NVRAM */
205 void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
206 {
207     m48t59_t *NVRAM = opaque;
208     struct tm tm;
209     int tmp;
210
211     if (addr > 0x1FF8 && addr < 0x2000)
212         NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
213     if (NVRAM->type == 8 &&
214         (addr >= 0x1ff0 && addr <= 0x1ff7))
215         goto do_write;
216     switch (addr) {
217     case 0x1FF0:
218         /* flags register : read-only */
219         break;
220     case 0x1FF1:
221         /* unused */
222         break;
223     case 0x1FF2:
224         /* alarm seconds */
225         tmp = fromBCD(val & 0x7F);
226         if (tmp >= 0 && tmp <= 59) {
227             get_alarm(NVRAM, &tm);
228             tm.tm_sec = tmp;
229             NVRAM->buffer[0x1FF2] = val;
230             set_alarm(NVRAM, &tm);
231         }
232         break;
233     case 0x1FF3:
234         /* alarm minutes */
235         tmp = fromBCD(val & 0x7F);
236         if (tmp >= 0 && tmp <= 59) {
237             get_alarm(NVRAM, &tm);
238             tm.tm_min = tmp;
239             NVRAM->buffer[0x1FF3] = val;
240             set_alarm(NVRAM, &tm);
241         }
242         break;
243     case 0x1FF4:
244         /* alarm hours */
245         tmp = fromBCD(val & 0x3F);
246         if (tmp >= 0 && tmp <= 23) {
247             get_alarm(NVRAM, &tm);
248             tm.tm_hour = tmp;
249             NVRAM->buffer[0x1FF4] = val;
250             set_alarm(NVRAM, &tm);
251         }
252         break;
253     case 0x1FF5:
254         /* alarm date */
255         tmp = fromBCD(val & 0x1F);
256         if (tmp != 0) {
257             get_alarm(NVRAM, &tm);
258             tm.tm_mday = tmp;
259             NVRAM->buffer[0x1FF5] = val;
260             set_alarm(NVRAM, &tm);
261         }
262         break;
263     case 0x1FF6:
264         /* interrupts */
265         NVRAM->buffer[0x1FF6] = val;
266         break;
267     case 0x1FF7:
268         /* watchdog */
269         NVRAM->buffer[0x1FF7] = val;
270         set_up_watchdog(NVRAM, val);
271         break;
272     case 0x1FF8:
273         /* control */
274         NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
275         break;
276     case 0x1FF9:
277         /* seconds (BCD) */
278         tmp = fromBCD(val & 0x7F);
279         if (tmp >= 0 && tmp <= 59) {
280             get_time(NVRAM, &tm);
281             tm.tm_sec = tmp;
282             set_time(NVRAM, &tm);
283         }
284         if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
285             if (val & 0x80) {
286                 NVRAM->stop_time = time(NULL);
287             } else {
288                 NVRAM->time_offset += NVRAM->stop_time - time(NULL);
289                 NVRAM->stop_time = 0;
290             }
291         }
292         NVRAM->buffer[0x1FF9] = val & 0x80;
293         break;
294     case 0x1FFA:
295         /* minutes (BCD) */
296         tmp = fromBCD(val & 0x7F);
297         if (tmp >= 0 && tmp <= 59) {
298             get_time(NVRAM, &tm);
299             tm.tm_min = tmp;
300             set_time(NVRAM, &tm);
301         }
302         break;
303     case 0x1FFB:
304         /* hours (BCD) */
305         tmp = fromBCD(val & 0x3F);
306         if (tmp >= 0 && tmp <= 23) {
307             get_time(NVRAM, &tm);
308             tm.tm_hour = tmp;
309             set_time(NVRAM, &tm);
310         }
311         break;
312     case 0x1FFC:
313         /* day of the week / century */
314         tmp = fromBCD(val & 0x07);
315         get_time(NVRAM, &tm);
316         tm.tm_wday = tmp;
317         set_time(NVRAM, &tm);
318         NVRAM->buffer[0x1FFC] = val & 0x40;
319         break;
320     case 0x1FFD:
321         /* date */
322         tmp = fromBCD(val & 0x1F);
323         if (tmp != 0) {
324             get_time(NVRAM, &tm);
325             tm.tm_mday = tmp;
326             set_time(NVRAM, &tm);
327         }
328         break;
329     case 0x1FFE:
330         /* month */
331         tmp = fromBCD(val & 0x1F);
332         if (tmp >= 1 && tmp <= 12) {
333             get_time(NVRAM, &tm);
334             tm.tm_mon = tmp - 1;
335             set_time(NVRAM, &tm);
336         }
337         break;
338     case 0x1FFF:
339         /* year */
340         tmp = fromBCD(val);
341         if (tmp >= 0 && tmp <= 99) {
342             get_time(NVRAM, &tm);
343             if (NVRAM->type == 8)
344                 tm.tm_year = fromBCD(val) + 68; // Base year is 1968
345             else
346                 tm.tm_year = fromBCD(val);
347             set_time(NVRAM, &tm);
348         }
349         break;
350     default:
351         /* Check lock registers state */
352         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
353             break;
354         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
355             break;
356     do_write:
357         if (addr < NVRAM->size) {
358             NVRAM->buffer[addr] = val & 0xFF;
359         }
360         break;
361     }
362 }
363
364 uint32_t m48t59_read (void *opaque, uint32_t addr)
365 {
366     m48t59_t *NVRAM = opaque;
367     struct tm tm;
368     uint32_t retval = 0xFF;
369
370     if (NVRAM->type == 8 &&
371         (addr >= 0x1ff0 && addr <= 0x1ff7))
372         goto do_read;
373     switch (addr) {
374     case 0x1FF0:
375         /* flags register */
376         goto do_read;
377     case 0x1FF1:
378         /* unused */
379         retval = 0;
380         break;
381     case 0x1FF2:
382         /* alarm seconds */
383         goto do_read;
384     case 0x1FF3:
385         /* alarm minutes */
386         goto do_read;
387     case 0x1FF4:
388         /* alarm hours */
389         goto do_read;
390     case 0x1FF5:
391         /* alarm date */
392         goto do_read;
393     case 0x1FF6:
394         /* interrupts */
395         goto do_read;
396     case 0x1FF7:
397         /* A read resets the watchdog */
398         set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
399         goto do_read;
400     case 0x1FF8:
401         /* control */
402         goto do_read;
403     case 0x1FF9:
404         /* seconds (BCD) */
405         get_time(NVRAM, &tm);
406         retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
407         break;
408     case 0x1FFA:
409         /* minutes (BCD) */
410         get_time(NVRAM, &tm);
411         retval = toBCD(tm.tm_min);
412         break;
413     case 0x1FFB:
414         /* hours (BCD) */
415         get_time(NVRAM, &tm);
416         retval = toBCD(tm.tm_hour);
417         break;
418     case 0x1FFC:
419         /* day of the week / century */
420         get_time(NVRAM, &tm);
421         retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
422         break;
423     case 0x1FFD:
424         /* date */
425         get_time(NVRAM, &tm);
426         retval = toBCD(tm.tm_mday);
427         break;
428     case 0x1FFE:
429         /* month */
430         get_time(NVRAM, &tm);
431         retval = toBCD(tm.tm_mon + 1);
432         break;
433     case 0x1FFF:
434         /* year */
435         get_time(NVRAM, &tm);
436         if (NVRAM->type == 8)
437             retval = toBCD(tm.tm_year - 68); // Base year is 1968
438         else
439             retval = toBCD(tm.tm_year);
440         break;
441     default:
442         /* Check lock registers state */
443         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
444             break;
445         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
446             break;
447     do_read:
448         if (addr < NVRAM->size) {
449             retval = NVRAM->buffer[addr];
450         }
451         break;
452     }
453     if (addr > 0x1FF9 && addr < 0x2000)
454        NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
455
456     return retval;
457 }
458
459 void m48t59_set_addr (void *opaque, uint32_t addr)
460 {
461     m48t59_t *NVRAM = opaque;
462
463     NVRAM->addr = addr;
464 }
465
466 void m48t59_toggle_lock (void *opaque, int lock)
467 {
468     m48t59_t *NVRAM = opaque;
469
470     NVRAM->lock ^= 1 << lock;
471 }
472
473 /* IO access to NVRAM */
474 static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
475 {
476     m48t59_t *NVRAM = opaque;
477
478     addr -= NVRAM->io_base;
479     NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
480     switch (addr) {
481     case 0:
482         NVRAM->addr &= ~0x00FF;
483         NVRAM->addr |= val;
484         break;
485     case 1:
486         NVRAM->addr &= ~0xFF00;
487         NVRAM->addr |= val << 8;
488         break;
489     case 3:
490         m48t59_write(NVRAM, val, NVRAM->addr);
491         NVRAM->addr = 0x0000;
492         break;
493     default:
494         break;
495     }
496 }
497
498 static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
499 {
500     m48t59_t *NVRAM = opaque;
501     uint32_t retval;
502
503     addr -= NVRAM->io_base;
504     switch (addr) {
505     case 3:
506         retval = m48t59_read(NVRAM, NVRAM->addr);
507         break;
508     default:
509         retval = -1;
510         break;
511     }
512     NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
513
514     return retval;
515 }
516
517 static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
518 {
519     m48t59_t *NVRAM = opaque;
520
521     addr -= NVRAM->mem_base;
522     m48t59_write(NVRAM, addr, value & 0xff);
523 }
524
525 static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
526 {
527     m48t59_t *NVRAM = opaque;
528
529     addr -= NVRAM->mem_base;
530     m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
531     m48t59_write(NVRAM, addr + 1, value & 0xff);
532 }
533
534 static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
535 {
536     m48t59_t *NVRAM = opaque;
537
538     addr -= NVRAM->mem_base;
539     m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
540     m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
541     m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
542     m48t59_write(NVRAM, addr + 3, value & 0xff);
543 }
544
545 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
546 {
547     m48t59_t *NVRAM = opaque;
548     uint32_t retval;
549
550     addr -= NVRAM->mem_base;
551     retval = m48t59_read(NVRAM, addr);
552     return retval;
553 }
554
555 static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
556 {
557     m48t59_t *NVRAM = opaque;
558     uint32_t retval;
559
560     addr -= NVRAM->mem_base;
561     retval = m48t59_read(NVRAM, addr) << 8;
562     retval |= m48t59_read(NVRAM, addr + 1);
563     return retval;
564 }
565
566 static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
567 {
568     m48t59_t *NVRAM = opaque;
569     uint32_t retval;
570
571     addr -= NVRAM->mem_base;
572     retval = m48t59_read(NVRAM, addr) << 24;
573     retval |= m48t59_read(NVRAM, addr + 1) << 16;
574     retval |= m48t59_read(NVRAM, addr + 2) << 8;
575     retval |= m48t59_read(NVRAM, addr + 3);
576     return retval;
577 }
578
579 static CPUWriteMemoryFunc *nvram_write[] = {
580     &nvram_writeb,
581     &nvram_writew,
582     &nvram_writel,
583 };
584
585 static CPUReadMemoryFunc *nvram_read[] = {
586     &nvram_readb,
587     &nvram_readw,
588     &nvram_readl,
589 };
590
591 static void m48t59_save(QEMUFile *f, void *opaque)
592 {
593     m48t59_t *s = opaque;
594
595     qemu_put_8s(f, &s->lock);
596     qemu_put_be16s(f, &s->addr);
597     qemu_put_buffer(f, s->buffer, s->size);
598 }
599
600 static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
601 {
602     m48t59_t *s = opaque;
603
604     if (version_id != 1)
605         return -EINVAL;
606
607     qemu_get_8s(f, &s->lock);
608     qemu_get_be16s(f, &s->addr);
609     qemu_get_buffer(f, s->buffer, s->size);
610
611     return 0;
612 }
613
614 static void m48t59_reset(void *opaque)
615 {
616     m48t59_t *NVRAM = opaque;
617
618     if (NVRAM->alrm_timer != NULL)
619         qemu_del_timer(NVRAM->alrm_timer);
620
621     if (NVRAM->wd_timer != NULL)
622         qemu_del_timer(NVRAM->wd_timer);
623 }
624
625 /* Initialisation routine */
626 m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
627                        uint32_t io_base, uint16_t size,
628                        int type)
629 {
630     m48t59_t *s;
631     target_phys_addr_t save_base;
632
633     s = qemu_mallocz(sizeof(m48t59_t));
634     if (!s)
635         return NULL;
636     s->buffer = qemu_mallocz(size);
637     if (!s->buffer) {
638         qemu_free(s);
639         return NULL;
640     }
641     s->IRQ = IRQ;
642     s->size = size;
643     s->mem_base = mem_base;
644     s->io_base = io_base;
645     s->addr = 0;
646     s->type = type;
647     if (io_base != 0) {
648         register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
649         register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
650     }
651     if (mem_base != 0) {
652         s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
653         cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
654     }
655     if (type == 59) {
656         s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
657         s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
658     }
659     s->lock = 0;
660
661     qemu_register_reset(m48t59_reset, s);
662     save_base = mem_base ? mem_base : io_base;
663     register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s);
664
665     return s;
666 }