]> Git Repo - qemu.git/blob - hw/timer/m48t59.c
ide: bdrv_attach_dev() for empty CD-ROM
[qemu.git] / hw / timer / m48t59.c
1 /*
2  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
3  *
4  * Copyright (c) 2003-2005, 2007, 2017 Jocelyn Mayer
5  * Copyright (c) 2013 HervĂ© Poussineau
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 #include "qemu/osdep.h"
26 #include "hw/hw.h"
27 #include "hw/timer/m48t59.h"
28 #include "qapi/error.h"
29 #include "qemu/timer.h"
30 #include "sysemu/sysemu.h"
31 #include "hw/sysbus.h"
32 #include "exec/address-spaces.h"
33 #include "qemu/bcd.h"
34
35 #include "m48t59-internal.h"
36
37 #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx"
38 #define M48TXX_SYS_BUS_GET_CLASS(obj) \
39     OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS)
40 #define M48TXX_SYS_BUS_CLASS(klass) \
41     OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
42 #define M48TXX_SYS_BUS(obj) \
43     OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
44
45 /*
46  * Chipset docs:
47  * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
48  * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf
49  * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf
50  */
51
52 typedef struct M48txxSysBusState {
53     SysBusDevice parent_obj;
54     M48t59State state;
55     MemoryRegion io;
56 } M48txxSysBusState;
57
58 typedef struct M48txxSysBusDeviceClass {
59     SysBusDeviceClass parent_class;
60     M48txxInfo info;
61 } M48txxSysBusDeviceClass;
62
63 static M48txxInfo m48txx_sysbus_info[] = {
64     {
65         .bus_name = "sysbus-m48t02",
66         .model = 2,
67         .size = 0x800,
68     },{
69         .bus_name = "sysbus-m48t08",
70         .model = 8,
71         .size = 0x2000,
72     },{
73         .bus_name = "sysbus-m48t59",
74         .model = 59,
75         .size = 0x2000,
76     }
77 };
78
79
80 /* Fake timer functions */
81
82 /* Alarm management */
83 static void alarm_cb (void *opaque)
84 {
85     struct tm tm;
86     uint64_t next_time;
87     M48t59State *NVRAM = opaque;
88
89     qemu_set_irq(NVRAM->IRQ, 1);
90     if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
91         (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
92         (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
93         (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
94         /* Repeat once a month */
95         qemu_get_timedate(&tm, NVRAM->time_offset);
96         tm.tm_mon++;
97         if (tm.tm_mon == 13) {
98             tm.tm_mon = 1;
99             tm.tm_year++;
100         }
101         next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
102     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
103                (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
104                (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
105                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
106         /* Repeat once a day */
107         next_time = 24 * 60 * 60;
108     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
109                (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
110                (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
111                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
112         /* Repeat once an hour */
113         next_time = 60 * 60;
114     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
115                (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
116                (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
117                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
118         /* Repeat once a minute */
119         next_time = 60;
120     } else {
121         /* Repeat once a second */
122         next_time = 1;
123     }
124     timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) +
125                     next_time * 1000);
126     qemu_set_irq(NVRAM->IRQ, 0);
127 }
128
129 static void set_alarm(M48t59State *NVRAM)
130 {
131     int diff;
132     if (NVRAM->alrm_timer != NULL) {
133         timer_del(NVRAM->alrm_timer);
134         diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
135         if (diff > 0)
136             timer_mod(NVRAM->alrm_timer, diff * 1000);
137     }
138 }
139
140 /* RTC management helpers */
141 static inline void get_time(M48t59State *NVRAM, struct tm *tm)
142 {
143     qemu_get_timedate(tm, NVRAM->time_offset);
144 }
145
146 static void set_time(M48t59State *NVRAM, struct tm *tm)
147 {
148     NVRAM->time_offset = qemu_timedate_diff(tm);
149     set_alarm(NVRAM);
150 }
151
152 /* Watchdog management */
153 static void watchdog_cb (void *opaque)
154 {
155     M48t59State *NVRAM = opaque;
156
157     NVRAM->buffer[0x1FF0] |= 0x80;
158     if (NVRAM->buffer[0x1FF7] & 0x80) {
159         NVRAM->buffer[0x1FF7] = 0x00;
160         NVRAM->buffer[0x1FFC] &= ~0x40;
161         /* May it be a hw CPU Reset instead ? */
162         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
163     } else {
164         qemu_set_irq(NVRAM->IRQ, 1);
165         qemu_set_irq(NVRAM->IRQ, 0);
166     }
167 }
168
169 static void set_up_watchdog(M48t59State *NVRAM, uint8_t value)
170 {
171     uint64_t interval; /* in 1/16 seconds */
172
173     NVRAM->buffer[0x1FF0] &= ~0x80;
174     if (NVRAM->wd_timer != NULL) {
175         timer_del(NVRAM->wd_timer);
176         if (value != 0) {
177             interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
178             timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
179                            ((interval * 1000) >> 4));
180         }
181     }
182 }
183
184 /* Direct access to NVRAM */
185 void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val)
186 {
187     struct tm tm;
188     int tmp;
189
190     if (addr > 0x1FF8 && addr < 0x2000)
191         NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
192
193     /* check for NVRAM access */
194     if ((NVRAM->model == 2 && addr < 0x7f8) ||
195         (NVRAM->model == 8 && addr < 0x1ff8) ||
196         (NVRAM->model == 59 && addr < 0x1ff0)) {
197         goto do_write;
198     }
199
200     /* TOD access */
201     switch (addr) {
202     case 0x1FF0:
203         /* flags register : read-only */
204         break;
205     case 0x1FF1:
206         /* unused */
207         break;
208     case 0x1FF2:
209         /* alarm seconds */
210         tmp = from_bcd(val & 0x7F);
211         if (tmp >= 0 && tmp <= 59) {
212             NVRAM->alarm.tm_sec = tmp;
213             NVRAM->buffer[0x1FF2] = val;
214             set_alarm(NVRAM);
215         }
216         break;
217     case 0x1FF3:
218         /* alarm minutes */
219         tmp = from_bcd(val & 0x7F);
220         if (tmp >= 0 && tmp <= 59) {
221             NVRAM->alarm.tm_min = tmp;
222             NVRAM->buffer[0x1FF3] = val;
223             set_alarm(NVRAM);
224         }
225         break;
226     case 0x1FF4:
227         /* alarm hours */
228         tmp = from_bcd(val & 0x3F);
229         if (tmp >= 0 && tmp <= 23) {
230             NVRAM->alarm.tm_hour = tmp;
231             NVRAM->buffer[0x1FF4] = val;
232             set_alarm(NVRAM);
233         }
234         break;
235     case 0x1FF5:
236         /* alarm date */
237         tmp = from_bcd(val & 0x3F);
238         if (tmp != 0) {
239             NVRAM->alarm.tm_mday = tmp;
240             NVRAM->buffer[0x1FF5] = val;
241             set_alarm(NVRAM);
242         }
243         break;
244     case 0x1FF6:
245         /* interrupts */
246         NVRAM->buffer[0x1FF6] = val;
247         break;
248     case 0x1FF7:
249         /* watchdog */
250         NVRAM->buffer[0x1FF7] = val;
251         set_up_watchdog(NVRAM, val);
252         break;
253     case 0x1FF8:
254     case 0x07F8:
255         /* control */
256        NVRAM->buffer[addr] = (val & ~0xA0) | 0x90;
257         break;
258     case 0x1FF9:
259     case 0x07F9:
260         /* seconds (BCD) */
261         tmp = from_bcd(val & 0x7F);
262         if (tmp >= 0 && tmp <= 59) {
263             get_time(NVRAM, &tm);
264             tm.tm_sec = tmp;
265             set_time(NVRAM, &tm);
266         }
267         if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
268             if (val & 0x80) {
269                 NVRAM->stop_time = time(NULL);
270             } else {
271                 NVRAM->time_offset += NVRAM->stop_time - time(NULL);
272                 NVRAM->stop_time = 0;
273             }
274         }
275         NVRAM->buffer[addr] = val & 0x80;
276         break;
277     case 0x1FFA:
278     case 0x07FA:
279         /* minutes (BCD) */
280         tmp = from_bcd(val & 0x7F);
281         if (tmp >= 0 && tmp <= 59) {
282             get_time(NVRAM, &tm);
283             tm.tm_min = tmp;
284             set_time(NVRAM, &tm);
285         }
286         break;
287     case 0x1FFB:
288     case 0x07FB:
289         /* hours (BCD) */
290         tmp = from_bcd(val & 0x3F);
291         if (tmp >= 0 && tmp <= 23) {
292             get_time(NVRAM, &tm);
293             tm.tm_hour = tmp;
294             set_time(NVRAM, &tm);
295         }
296         break;
297     case 0x1FFC:
298     case 0x07FC:
299         /* day of the week / century */
300         tmp = from_bcd(val & 0x07);
301         get_time(NVRAM, &tm);
302         tm.tm_wday = tmp;
303         set_time(NVRAM, &tm);
304         NVRAM->buffer[addr] = val & 0x40;
305         break;
306     case 0x1FFD:
307     case 0x07FD:
308         /* date (BCD) */
309        tmp = from_bcd(val & 0x3F);
310         if (tmp != 0) {
311             get_time(NVRAM, &tm);
312             tm.tm_mday = tmp;
313             set_time(NVRAM, &tm);
314         }
315         break;
316     case 0x1FFE:
317     case 0x07FE:
318         /* month */
319         tmp = from_bcd(val & 0x1F);
320         if (tmp >= 1 && tmp <= 12) {
321             get_time(NVRAM, &tm);
322             tm.tm_mon = tmp - 1;
323             set_time(NVRAM, &tm);
324         }
325         break;
326     case 0x1FFF:
327     case 0x07FF:
328         /* year */
329         tmp = from_bcd(val);
330         if (tmp >= 0 && tmp <= 99) {
331             get_time(NVRAM, &tm);
332             tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900;
333             set_time(NVRAM, &tm);
334         }
335         break;
336     default:
337         /* Check lock registers state */
338         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
339             break;
340         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
341             break;
342     do_write:
343         if (addr < NVRAM->size) {
344             NVRAM->buffer[addr] = val & 0xFF;
345         }
346         break;
347     }
348 }
349
350 uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr)
351 {
352     struct tm tm;
353     uint32_t retval = 0xFF;
354
355     /* check for NVRAM access */
356     if ((NVRAM->model == 2 && addr < 0x078f) ||
357         (NVRAM->model == 8 && addr < 0x1ff8) ||
358         (NVRAM->model == 59 && addr < 0x1ff0)) {
359         goto do_read;
360     }
361
362     /* TOD access */
363     switch (addr) {
364     case 0x1FF0:
365         /* flags register */
366         goto do_read;
367     case 0x1FF1:
368         /* unused */
369         retval = 0;
370         break;
371     case 0x1FF2:
372         /* alarm seconds */
373         goto do_read;
374     case 0x1FF3:
375         /* alarm minutes */
376         goto do_read;
377     case 0x1FF4:
378         /* alarm hours */
379         goto do_read;
380     case 0x1FF5:
381         /* alarm date */
382         goto do_read;
383     case 0x1FF6:
384         /* interrupts */
385         goto do_read;
386     case 0x1FF7:
387         /* A read resets the watchdog */
388         set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
389         goto do_read;
390     case 0x1FF8:
391     case 0x07F8:
392         /* control */
393         goto do_read;
394     case 0x1FF9:
395     case 0x07F9:
396         /* seconds (BCD) */
397         get_time(NVRAM, &tm);
398         retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec);
399         break;
400     case 0x1FFA:
401     case 0x07FA:
402         /* minutes (BCD) */
403         get_time(NVRAM, &tm);
404         retval = to_bcd(tm.tm_min);
405         break;
406     case 0x1FFB:
407     case 0x07FB:
408         /* hours (BCD) */
409         get_time(NVRAM, &tm);
410         retval = to_bcd(tm.tm_hour);
411         break;
412     case 0x1FFC:
413     case 0x07FC:
414         /* day of the week / century */
415         get_time(NVRAM, &tm);
416         retval = NVRAM->buffer[addr] | tm.tm_wday;
417         break;
418     case 0x1FFD:
419     case 0x07FD:
420         /* date */
421         get_time(NVRAM, &tm);
422         retval = to_bcd(tm.tm_mday);
423         break;
424     case 0x1FFE:
425     case 0x07FE:
426         /* month */
427         get_time(NVRAM, &tm);
428         retval = to_bcd(tm.tm_mon + 1);
429         break;
430     case 0x1FFF:
431     case 0x07FF:
432         /* year */
433         get_time(NVRAM, &tm);
434         retval = to_bcd((tm.tm_year + 1900 - NVRAM->base_year) % 100);
435         break;
436     default:
437         /* Check lock registers state */
438         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
439             break;
440         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
441             break;
442     do_read:
443         if (addr < NVRAM->size) {
444             retval = NVRAM->buffer[addr];
445         }
446         break;
447     }
448     if (addr > 0x1FF9 && addr < 0x2000)
449        NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
450
451     return retval;
452 }
453
454 /* IO access to NVRAM */
455 static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val,
456                          unsigned size)
457 {
458     M48t59State *NVRAM = opaque;
459
460     NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
461     switch (addr) {
462     case 0:
463         NVRAM->addr &= ~0x00FF;
464         NVRAM->addr |= val;
465         break;
466     case 1:
467         NVRAM->addr &= ~0xFF00;
468         NVRAM->addr |= val << 8;
469         break;
470     case 3:
471         m48t59_write(NVRAM, NVRAM->addr, val);
472         NVRAM->addr = 0x0000;
473         break;
474     default:
475         break;
476     }
477 }
478
479 static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
480 {
481     M48t59State *NVRAM = opaque;
482     uint32_t retval;
483
484     switch (addr) {
485     case 3:
486         retval = m48t59_read(NVRAM, NVRAM->addr);
487         break;
488     default:
489         retval = -1;
490         break;
491     }
492     NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
493
494     return retval;
495 }
496
497 static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value)
498 {
499     M48t59State *NVRAM = opaque;
500
501     m48t59_write(NVRAM, addr, value & 0xff);
502 }
503
504 static void nvram_writew (void *opaque, hwaddr addr, uint32_t value)
505 {
506     M48t59State *NVRAM = opaque;
507
508     m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
509     m48t59_write(NVRAM, addr + 1, value & 0xff);
510 }
511
512 static void nvram_writel (void *opaque, hwaddr addr, uint32_t value)
513 {
514     M48t59State *NVRAM = opaque;
515
516     m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
517     m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
518     m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
519     m48t59_write(NVRAM, addr + 3, value & 0xff);
520 }
521
522 static uint32_t nvram_readb (void *opaque, hwaddr addr)
523 {
524     M48t59State *NVRAM = opaque;
525
526     return m48t59_read(NVRAM, addr);
527 }
528
529 static uint32_t nvram_readw (void *opaque, hwaddr addr)
530 {
531     M48t59State *NVRAM = opaque;
532     uint32_t retval;
533
534     retval = m48t59_read(NVRAM, addr) << 8;
535     retval |= m48t59_read(NVRAM, addr + 1);
536     return retval;
537 }
538
539 static uint32_t nvram_readl (void *opaque, hwaddr addr)
540 {
541     M48t59State *NVRAM = opaque;
542     uint32_t retval;
543
544     retval = m48t59_read(NVRAM, addr) << 24;
545     retval |= m48t59_read(NVRAM, addr + 1) << 16;
546     retval |= m48t59_read(NVRAM, addr + 2) << 8;
547     retval |= m48t59_read(NVRAM, addr + 3);
548     return retval;
549 }
550
551 static const MemoryRegionOps nvram_ops = {
552     .old_mmio = {
553         .read = { nvram_readb, nvram_readw, nvram_readl, },
554         .write = { nvram_writeb, nvram_writew, nvram_writel, },
555     },
556     .endianness = DEVICE_NATIVE_ENDIAN,
557 };
558
559 static const VMStateDescription vmstate_m48t59 = {
560     .name = "m48t59",
561     .version_id = 1,
562     .minimum_version_id = 1,
563     .fields = (VMStateField[]) {
564         VMSTATE_UINT8(lock, M48t59State),
565         VMSTATE_UINT16(addr, M48t59State),
566         VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, size),
567         VMSTATE_END_OF_LIST()
568     }
569 };
570
571 void m48t59_reset_common(M48t59State *NVRAM)
572 {
573     NVRAM->addr = 0;
574     NVRAM->lock = 0;
575     if (NVRAM->alrm_timer != NULL)
576         timer_del(NVRAM->alrm_timer);
577
578     if (NVRAM->wd_timer != NULL)
579         timer_del(NVRAM->wd_timer);
580 }
581
582 static void m48t59_reset_sysbus(DeviceState *d)
583 {
584     M48txxSysBusState *sys = M48TXX_SYS_BUS(d);
585     M48t59State *NVRAM = &sys->state;
586
587     m48t59_reset_common(NVRAM);
588 }
589
590 const MemoryRegionOps m48t59_io_ops = {
591     .read = NVRAM_readb,
592     .write = NVRAM_writeb,
593     .impl = {
594         .min_access_size = 1,
595         .max_access_size = 1,
596     },
597     .endianness = DEVICE_LITTLE_ENDIAN,
598 };
599
600 /* Initialisation routine */
601 Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
602                    uint32_t io_base, uint16_t size, int base_year,
603                    int model)
604 {
605     DeviceState *dev;
606     SysBusDevice *s;
607     int i;
608
609     for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) {
610         if (m48txx_sysbus_info[i].size != size ||
611             m48txx_sysbus_info[i].model != model) {
612             continue;
613         }
614
615         dev = qdev_create(NULL, m48txx_sysbus_info[i].bus_name);
616         qdev_prop_set_int32(dev, "base-year", base_year);
617         qdev_init_nofail(dev);
618         s = SYS_BUS_DEVICE(dev);
619         sysbus_connect_irq(s, 0, IRQ);
620         if (io_base != 0) {
621             memory_region_add_subregion(get_system_io(), io_base,
622                                         sysbus_mmio_get_region(s, 1));
623         }
624         if (mem_base != 0) {
625             sysbus_mmio_map(s, 0, mem_base);
626         }
627
628         return NVRAM(s);
629     }
630
631     assert(false);
632     return NULL;
633 }
634
635 void m48t59_realize_common(M48t59State *s, Error **errp)
636 {
637     s->buffer = g_malloc0(s->size);
638     if (s->model == 59) {
639         s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s);
640         s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s);
641     }
642     qemu_get_timedate(&s->alarm, 0);
643 }
644
645 static void m48t59_init1(Object *obj)
646 {
647     M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(obj);
648     M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
649     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
650     M48t59State *s = &d->state;
651
652     s->model = u->info.model;
653     s->size = u->info.size;
654     sysbus_init_irq(dev, &s->IRQ);
655
656     memory_region_init_io(&s->iomem, obj, &nvram_ops, s, "m48t59.nvram",
657                           s->size);
658     memory_region_init_io(&d->io, obj, &m48t59_io_ops, s, "m48t59", 4);
659 }
660
661 static void m48t59_realize(DeviceState *dev, Error **errp)
662 {
663     M48txxSysBusState *d = M48TXX_SYS_BUS(dev);
664     M48t59State *s = &d->state;
665     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
666
667     sysbus_init_mmio(sbd, &s->iomem);
668     sysbus_init_mmio(sbd, &d->io);
669     m48t59_realize_common(s, errp);
670 }
671
672 static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr)
673 {
674     M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
675     return m48t59_read(&d->state, addr);
676 }
677
678 static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val)
679 {
680     M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
681     m48t59_write(&d->state, addr, val);
682 }
683
684 static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock)
685 {
686     M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
687     m48t59_toggle_lock(&d->state, lock);
688 }
689
690 static Property m48t59_sysbus_properties[] = {
691     DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0),
692     DEFINE_PROP_END_OF_LIST(),
693 };
694
695 static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
696 {
697     DeviceClass *dc = DEVICE_CLASS(klass);
698     NvramClass *nc = NVRAM_CLASS(klass);
699
700     dc->realize = m48t59_realize;
701     dc->reset = m48t59_reset_sysbus;
702     dc->props = m48t59_sysbus_properties;
703     dc->vmsd = &vmstate_m48t59;
704     nc->read = m48txx_sysbus_read;
705     nc->write = m48txx_sysbus_write;
706     nc->toggle_lock = m48txx_sysbus_toggle_lock;
707 }
708
709 static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data)
710 {
711     M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
712     M48txxInfo *info = data;
713
714     u->info = *info;
715 }
716
717 static const TypeInfo nvram_info = {
718     .name = TYPE_NVRAM,
719     .parent = TYPE_INTERFACE,
720     .class_size = sizeof(NvramClass),
721 };
722
723 static const TypeInfo m48txx_sysbus_type_info = {
724     .name = TYPE_M48TXX_SYS_BUS,
725     .parent = TYPE_SYS_BUS_DEVICE,
726     .instance_size = sizeof(M48txxSysBusState),
727     .instance_init = m48t59_init1,
728     .abstract = true,
729     .class_init = m48txx_sysbus_class_init,
730     .interfaces = (InterfaceInfo[]) {
731         { TYPE_NVRAM },
732         { }
733     }
734 };
735
736 static void m48t59_register_types(void)
737 {
738     TypeInfo sysbus_type_info = {
739         .parent = TYPE_M48TXX_SYS_BUS,
740         .class_size = sizeof(M48txxSysBusDeviceClass),
741         .class_init = m48txx_sysbus_concrete_class_init,
742     };
743     int i;
744
745     type_register_static(&nvram_info);
746     type_register_static(&m48txx_sysbus_type_info);
747
748     for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) {
749         sysbus_type_info.name = m48txx_sysbus_info[i].bus_name;
750         sysbus_type_info.class_data = &m48txx_sysbus_info[i];
751         type_register(&sysbus_type_info);
752     }
753 }
754
755 type_init(m48t59_register_types)
This page took 0.066721 seconds and 4 git commands to generate.