crypto: skip testing of unsupported cipher algorithms
[qemu.git] / hw / timer / m48t59.c
blobbbcfeb2192bfc78906b4a0ffe2fa36f396dcf4a4
1 /*
2 * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
4 * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
5 * Copyright (c) 2013 Hervé Poussineau
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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.
25 #include "qemu/osdep.h"
26 #include "hw/hw.h"
27 #include "hw/timer/m48t59.h"
28 #include "qemu/timer.h"
29 #include "sysemu/sysemu.h"
30 #include "hw/sysbus.h"
31 #include "hw/isa/isa.h"
32 #include "exec/address-spaces.h"
34 //#define DEBUG_NVRAM
36 #if defined(DEBUG_NVRAM)
37 #define NVRAM_PRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
38 #else
39 #define NVRAM_PRINTF(fmt, ...) do { } while (0)
40 #endif
42 #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx"
43 #define M48TXX_SYS_BUS_GET_CLASS(obj) \
44 OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS)
45 #define M48TXX_SYS_BUS_CLASS(klass) \
46 OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
47 #define M48TXX_SYS_BUS(obj) \
48 OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
50 #define TYPE_M48TXX_ISA "isa-m48txx"
51 #define M48TXX_ISA_GET_CLASS(obj) \
52 OBJECT_GET_CLASS(M48txxISADeviceClass, (obj), TYPE_M48TXX_ISA)
53 #define M48TXX_ISA_CLASS(klass) \
54 OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA)
55 #define M48TXX_ISA(obj) \
56 OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA)
59 * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
60 * alarm and a watchdog timer and related control registers. In the
61 * PPC platform there is also a nvram lock function.
64 typedef struct M48txxInfo {
65 const char *isa_name;
66 const char *sysbus_name;
67 uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
68 uint32_t size;
69 } M48txxInfo;
72 * Chipset docs:
73 * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
74 * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf
75 * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf
78 typedef struct M48t59State {
79 /* Hardware parameters */
80 qemu_irq IRQ;
81 MemoryRegion iomem;
82 uint32_t size;
83 int32_t base_year;
84 /* RTC management */
85 time_t time_offset;
86 time_t stop_time;
87 /* Alarm & watchdog */
88 struct tm alarm;
89 QEMUTimer *alrm_timer;
90 QEMUTimer *wd_timer;
91 /* NVRAM storage */
92 uint8_t *buffer;
93 /* Model parameters */
94 uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
95 /* NVRAM storage */
96 uint16_t addr;
97 uint8_t lock;
98 } M48t59State;
100 typedef struct M48txxISAState {
101 ISADevice parent_obj;
102 M48t59State state;
103 uint32_t io_base;
104 MemoryRegion io;
105 } M48txxISAState;
107 typedef struct M48txxISADeviceClass {
108 ISADeviceClass parent_class;
109 M48txxInfo info;
110 } M48txxISADeviceClass;
112 typedef struct M48txxSysBusState {
113 SysBusDevice parent_obj;
114 M48t59State state;
115 MemoryRegion io;
116 } M48txxSysBusState;
118 typedef struct M48txxSysBusDeviceClass {
119 SysBusDeviceClass parent_class;
120 M48txxInfo info;
121 } M48txxSysBusDeviceClass;
123 static M48txxInfo m48txx_info[] = {
125 .sysbus_name = "sysbus-m48t02",
126 .model = 2,
127 .size = 0x800,
129 .sysbus_name = "sysbus-m48t08",
130 .model = 8,
131 .size = 0x2000,
133 .sysbus_name = "sysbus-m48t59",
134 .model = 59,
135 .size = 0x2000,
137 .isa_name = "isa-m48t59",
138 .model = 59,
139 .size = 0x2000,
144 /* Fake timer functions */
146 /* Alarm management */
147 static void alarm_cb (void *opaque)
149 struct tm tm;
150 uint64_t next_time;
151 M48t59State *NVRAM = opaque;
153 qemu_set_irq(NVRAM->IRQ, 1);
154 if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
155 (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
156 (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
157 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
158 /* Repeat once a month */
159 qemu_get_timedate(&tm, NVRAM->time_offset);
160 tm.tm_mon++;
161 if (tm.tm_mon == 13) {
162 tm.tm_mon = 1;
163 tm.tm_year++;
165 next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
166 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
167 (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
168 (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
169 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
170 /* Repeat once a day */
171 next_time = 24 * 60 * 60;
172 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
173 (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
174 (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
175 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
176 /* Repeat once an hour */
177 next_time = 60 * 60;
178 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
179 (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
180 (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
181 (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
182 /* Repeat once a minute */
183 next_time = 60;
184 } else {
185 /* Repeat once a second */
186 next_time = 1;
188 timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) +
189 next_time * 1000);
190 qemu_set_irq(NVRAM->IRQ, 0);
193 static void set_alarm(M48t59State *NVRAM)
195 int diff;
196 if (NVRAM->alrm_timer != NULL) {
197 timer_del(NVRAM->alrm_timer);
198 diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
199 if (diff > 0)
200 timer_mod(NVRAM->alrm_timer, diff * 1000);
204 /* RTC management helpers */
205 static inline void get_time(M48t59State *NVRAM, struct tm *tm)
207 qemu_get_timedate(tm, NVRAM->time_offset);
210 static void set_time(M48t59State *NVRAM, struct tm *tm)
212 NVRAM->time_offset = qemu_timedate_diff(tm);
213 set_alarm(NVRAM);
216 /* Watchdog management */
217 static void watchdog_cb (void *opaque)
219 M48t59State *NVRAM = opaque;
221 NVRAM->buffer[0x1FF0] |= 0x80;
222 if (NVRAM->buffer[0x1FF7] & 0x80) {
223 NVRAM->buffer[0x1FF7] = 0x00;
224 NVRAM->buffer[0x1FFC] &= ~0x40;
225 /* May it be a hw CPU Reset instead ? */
226 qemu_system_reset_request();
227 } else {
228 qemu_set_irq(NVRAM->IRQ, 1);
229 qemu_set_irq(NVRAM->IRQ, 0);
233 static void set_up_watchdog(M48t59State *NVRAM, uint8_t value)
235 uint64_t interval; /* in 1/16 seconds */
237 NVRAM->buffer[0x1FF0] &= ~0x80;
238 if (NVRAM->wd_timer != NULL) {
239 timer_del(NVRAM->wd_timer);
240 if (value != 0) {
241 interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
242 timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
243 ((interval * 1000) >> 4));
248 /* Direct access to NVRAM */
249 static void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val)
251 struct tm tm;
252 int tmp;
254 if (addr > 0x1FF8 && addr < 0x2000)
255 NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
257 /* check for NVRAM access */
258 if ((NVRAM->model == 2 && addr < 0x7f8) ||
259 (NVRAM->model == 8 && addr < 0x1ff8) ||
260 (NVRAM->model == 59 && addr < 0x1ff0)) {
261 goto do_write;
264 /* TOD access */
265 switch (addr) {
266 case 0x1FF0:
267 /* flags register : read-only */
268 break;
269 case 0x1FF1:
270 /* unused */
271 break;
272 case 0x1FF2:
273 /* alarm seconds */
274 tmp = from_bcd(val & 0x7F);
275 if (tmp >= 0 && tmp <= 59) {
276 NVRAM->alarm.tm_sec = tmp;
277 NVRAM->buffer[0x1FF2] = val;
278 set_alarm(NVRAM);
280 break;
281 case 0x1FF3:
282 /* alarm minutes */
283 tmp = from_bcd(val & 0x7F);
284 if (tmp >= 0 && tmp <= 59) {
285 NVRAM->alarm.tm_min = tmp;
286 NVRAM->buffer[0x1FF3] = val;
287 set_alarm(NVRAM);
289 break;
290 case 0x1FF4:
291 /* alarm hours */
292 tmp = from_bcd(val & 0x3F);
293 if (tmp >= 0 && tmp <= 23) {
294 NVRAM->alarm.tm_hour = tmp;
295 NVRAM->buffer[0x1FF4] = val;
296 set_alarm(NVRAM);
298 break;
299 case 0x1FF5:
300 /* alarm date */
301 tmp = from_bcd(val & 0x3F);
302 if (tmp != 0) {
303 NVRAM->alarm.tm_mday = tmp;
304 NVRAM->buffer[0x1FF5] = val;
305 set_alarm(NVRAM);
307 break;
308 case 0x1FF6:
309 /* interrupts */
310 NVRAM->buffer[0x1FF6] = val;
311 break;
312 case 0x1FF7:
313 /* watchdog */
314 NVRAM->buffer[0x1FF7] = val;
315 set_up_watchdog(NVRAM, val);
316 break;
317 case 0x1FF8:
318 case 0x07F8:
319 /* control */
320 NVRAM->buffer[addr] = (val & ~0xA0) | 0x90;
321 break;
322 case 0x1FF9:
323 case 0x07F9:
324 /* seconds (BCD) */
325 tmp = from_bcd(val & 0x7F);
326 if (tmp >= 0 && tmp <= 59) {
327 get_time(NVRAM, &tm);
328 tm.tm_sec = tmp;
329 set_time(NVRAM, &tm);
331 if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
332 if (val & 0x80) {
333 NVRAM->stop_time = time(NULL);
334 } else {
335 NVRAM->time_offset += NVRAM->stop_time - time(NULL);
336 NVRAM->stop_time = 0;
339 NVRAM->buffer[addr] = val & 0x80;
340 break;
341 case 0x1FFA:
342 case 0x07FA:
343 /* minutes (BCD) */
344 tmp = from_bcd(val & 0x7F);
345 if (tmp >= 0 && tmp <= 59) {
346 get_time(NVRAM, &tm);
347 tm.tm_min = tmp;
348 set_time(NVRAM, &tm);
350 break;
351 case 0x1FFB:
352 case 0x07FB:
353 /* hours (BCD) */
354 tmp = from_bcd(val & 0x3F);
355 if (tmp >= 0 && tmp <= 23) {
356 get_time(NVRAM, &tm);
357 tm.tm_hour = tmp;
358 set_time(NVRAM, &tm);
360 break;
361 case 0x1FFC:
362 case 0x07FC:
363 /* day of the week / century */
364 tmp = from_bcd(val & 0x07);
365 get_time(NVRAM, &tm);
366 tm.tm_wday = tmp;
367 set_time(NVRAM, &tm);
368 NVRAM->buffer[addr] = val & 0x40;
369 break;
370 case 0x1FFD:
371 case 0x07FD:
372 /* date (BCD) */
373 tmp = from_bcd(val & 0x3F);
374 if (tmp != 0) {
375 get_time(NVRAM, &tm);
376 tm.tm_mday = tmp;
377 set_time(NVRAM, &tm);
379 break;
380 case 0x1FFE:
381 case 0x07FE:
382 /* month */
383 tmp = from_bcd(val & 0x1F);
384 if (tmp >= 1 && tmp <= 12) {
385 get_time(NVRAM, &tm);
386 tm.tm_mon = tmp - 1;
387 set_time(NVRAM, &tm);
389 break;
390 case 0x1FFF:
391 case 0x07FF:
392 /* year */
393 tmp = from_bcd(val);
394 if (tmp >= 0 && tmp <= 99) {
395 get_time(NVRAM, &tm);
396 tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900;
397 set_time(NVRAM, &tm);
399 break;
400 default:
401 /* Check lock registers state */
402 if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
403 break;
404 if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
405 break;
406 do_write:
407 if (addr < NVRAM->size) {
408 NVRAM->buffer[addr] = val & 0xFF;
410 break;
414 static uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr)
416 struct tm tm;
417 uint32_t retval = 0xFF;
419 /* check for NVRAM access */
420 if ((NVRAM->model == 2 && addr < 0x078f) ||
421 (NVRAM->model == 8 && addr < 0x1ff8) ||
422 (NVRAM->model == 59 && addr < 0x1ff0)) {
423 goto do_read;
426 /* TOD access */
427 switch (addr) {
428 case 0x1FF0:
429 /* flags register */
430 goto do_read;
431 case 0x1FF1:
432 /* unused */
433 retval = 0;
434 break;
435 case 0x1FF2:
436 /* alarm seconds */
437 goto do_read;
438 case 0x1FF3:
439 /* alarm minutes */
440 goto do_read;
441 case 0x1FF4:
442 /* alarm hours */
443 goto do_read;
444 case 0x1FF5:
445 /* alarm date */
446 goto do_read;
447 case 0x1FF6:
448 /* interrupts */
449 goto do_read;
450 case 0x1FF7:
451 /* A read resets the watchdog */
452 set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
453 goto do_read;
454 case 0x1FF8:
455 case 0x07F8:
456 /* control */
457 goto do_read;
458 case 0x1FF9:
459 case 0x07F9:
460 /* seconds (BCD) */
461 get_time(NVRAM, &tm);
462 retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec);
463 break;
464 case 0x1FFA:
465 case 0x07FA:
466 /* minutes (BCD) */
467 get_time(NVRAM, &tm);
468 retval = to_bcd(tm.tm_min);
469 break;
470 case 0x1FFB:
471 case 0x07FB:
472 /* hours (BCD) */
473 get_time(NVRAM, &tm);
474 retval = to_bcd(tm.tm_hour);
475 break;
476 case 0x1FFC:
477 case 0x07FC:
478 /* day of the week / century */
479 get_time(NVRAM, &tm);
480 retval = NVRAM->buffer[addr] | tm.tm_wday;
481 break;
482 case 0x1FFD:
483 case 0x07FD:
484 /* date */
485 get_time(NVRAM, &tm);
486 retval = to_bcd(tm.tm_mday);
487 break;
488 case 0x1FFE:
489 case 0x07FE:
490 /* month */
491 get_time(NVRAM, &tm);
492 retval = to_bcd(tm.tm_mon + 1);
493 break;
494 case 0x1FFF:
495 case 0x07FF:
496 /* year */
497 get_time(NVRAM, &tm);
498 retval = to_bcd((tm.tm_year + 1900 - NVRAM->base_year) % 100);
499 break;
500 default:
501 /* Check lock registers state */
502 if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
503 break;
504 if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
505 break;
506 do_read:
507 if (addr < NVRAM->size) {
508 retval = NVRAM->buffer[addr];
510 break;
512 if (addr > 0x1FF9 && addr < 0x2000)
513 NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
515 return retval;
518 static void m48t59_toggle_lock(M48t59State *NVRAM, int lock)
520 NVRAM->lock ^= 1 << lock;
523 /* IO access to NVRAM */
524 static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val,
525 unsigned size)
527 M48t59State *NVRAM = opaque;
529 NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
530 switch (addr) {
531 case 0:
532 NVRAM->addr &= ~0x00FF;
533 NVRAM->addr |= val;
534 break;
535 case 1:
536 NVRAM->addr &= ~0xFF00;
537 NVRAM->addr |= val << 8;
538 break;
539 case 3:
540 m48t59_write(NVRAM, NVRAM->addr, val);
541 NVRAM->addr = 0x0000;
542 break;
543 default:
544 break;
548 static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
550 M48t59State *NVRAM = opaque;
551 uint32_t retval;
553 switch (addr) {
554 case 3:
555 retval = m48t59_read(NVRAM, NVRAM->addr);
556 break;
557 default:
558 retval = -1;
559 break;
561 NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
563 return retval;
566 static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value)
568 M48t59State *NVRAM = opaque;
570 m48t59_write(NVRAM, addr, value & 0xff);
573 static void nvram_writew (void *opaque, hwaddr addr, uint32_t value)
575 M48t59State *NVRAM = opaque;
577 m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
578 m48t59_write(NVRAM, addr + 1, value & 0xff);
581 static void nvram_writel (void *opaque, hwaddr addr, uint32_t value)
583 M48t59State *NVRAM = opaque;
585 m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
586 m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
587 m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
588 m48t59_write(NVRAM, addr + 3, value & 0xff);
591 static uint32_t nvram_readb (void *opaque, hwaddr addr)
593 M48t59State *NVRAM = opaque;
595 return m48t59_read(NVRAM, addr);
598 static uint32_t nvram_readw (void *opaque, hwaddr addr)
600 M48t59State *NVRAM = opaque;
601 uint32_t retval;
603 retval = m48t59_read(NVRAM, addr) << 8;
604 retval |= m48t59_read(NVRAM, addr + 1);
605 return retval;
608 static uint32_t nvram_readl (void *opaque, hwaddr addr)
610 M48t59State *NVRAM = opaque;
611 uint32_t retval;
613 retval = m48t59_read(NVRAM, addr) << 24;
614 retval |= m48t59_read(NVRAM, addr + 1) << 16;
615 retval |= m48t59_read(NVRAM, addr + 2) << 8;
616 retval |= m48t59_read(NVRAM, addr + 3);
617 return retval;
620 static const MemoryRegionOps nvram_ops = {
621 .old_mmio = {
622 .read = { nvram_readb, nvram_readw, nvram_readl, },
623 .write = { nvram_writeb, nvram_writew, nvram_writel, },
625 .endianness = DEVICE_NATIVE_ENDIAN,
628 static const VMStateDescription vmstate_m48t59 = {
629 .name = "m48t59",
630 .version_id = 1,
631 .minimum_version_id = 1,
632 .fields = (VMStateField[]) {
633 VMSTATE_UINT8(lock, M48t59State),
634 VMSTATE_UINT16(addr, M48t59State),
635 VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size),
636 VMSTATE_END_OF_LIST()
640 static void m48t59_reset_common(M48t59State *NVRAM)
642 NVRAM->addr = 0;
643 NVRAM->lock = 0;
644 if (NVRAM->alrm_timer != NULL)
645 timer_del(NVRAM->alrm_timer);
647 if (NVRAM->wd_timer != NULL)
648 timer_del(NVRAM->wd_timer);
651 static void m48t59_reset_isa(DeviceState *d)
653 M48txxISAState *isa = M48TXX_ISA(d);
654 M48t59State *NVRAM = &isa->state;
656 m48t59_reset_common(NVRAM);
659 static void m48t59_reset_sysbus(DeviceState *d)
661 M48txxSysBusState *sys = M48TXX_SYS_BUS(d);
662 M48t59State *NVRAM = &sys->state;
664 m48t59_reset_common(NVRAM);
667 static const MemoryRegionOps m48t59_io_ops = {
668 .read = NVRAM_readb,
669 .write = NVRAM_writeb,
670 .impl = {
671 .min_access_size = 1,
672 .max_access_size = 1,
674 .endianness = DEVICE_LITTLE_ENDIAN,
677 /* Initialisation routine */
678 Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
679 uint32_t io_base, uint16_t size, int base_year,
680 int model)
682 DeviceState *dev;
683 SysBusDevice *s;
684 int i;
686 for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
687 if (!m48txx_info[i].sysbus_name ||
688 m48txx_info[i].size != size ||
689 m48txx_info[i].model != model) {
690 continue;
693 dev = qdev_create(NULL, m48txx_info[i].sysbus_name);
694 qdev_prop_set_int32(dev, "base-year", base_year);
695 qdev_init_nofail(dev);
696 s = SYS_BUS_DEVICE(dev);
697 sysbus_connect_irq(s, 0, IRQ);
698 if (io_base != 0) {
699 memory_region_add_subregion(get_system_io(), io_base,
700 sysbus_mmio_get_region(s, 1));
702 if (mem_base != 0) {
703 sysbus_mmio_map(s, 0, mem_base);
706 return NVRAM(s);
709 assert(false);
710 return NULL;
713 Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
714 int base_year, int model)
716 DeviceState *dev;
717 int i;
719 for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
720 if (!m48txx_info[i].isa_name ||
721 m48txx_info[i].size != size ||
722 m48txx_info[i].model != model) {
723 continue;
726 dev = DEVICE(isa_create(bus, m48txx_info[i].isa_name));
727 qdev_prop_set_uint32(dev, "iobase", io_base);
728 qdev_prop_set_int32(dev, "base-year", base_year);
729 qdev_init_nofail(dev);
730 return NVRAM(dev);
733 assert(false);
734 return NULL;
737 static void m48t59_realize_common(M48t59State *s, Error **errp)
739 s->buffer = g_malloc0(s->size);
740 if (s->model == 59) {
741 s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s);
742 s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s);
744 qemu_get_timedate(&s->alarm, 0);
746 vmstate_register(NULL, -1, &vmstate_m48t59, s);
749 static void m48t59_isa_realize(DeviceState *dev, Error **errp)
751 M48txxISADeviceClass *u = M48TXX_ISA_GET_CLASS(dev);
752 ISADevice *isadev = ISA_DEVICE(dev);
753 M48txxISAState *d = M48TXX_ISA(dev);
754 M48t59State *s = &d->state;
756 s->model = u->info.model;
757 s->size = u->info.size;
758 isa_init_irq(isadev, &s->IRQ, 8);
759 m48t59_realize_common(s, errp);
760 memory_region_init_io(&d->io, OBJECT(dev), &m48t59_io_ops, s, "m48t59", 4);
761 if (d->io_base != 0) {
762 isa_register_ioport(isadev, &d->io, d->io_base);
766 static int m48t59_init1(SysBusDevice *dev)
768 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(dev);
769 M48txxSysBusState *d = M48TXX_SYS_BUS(dev);
770 Object *o = OBJECT(dev);
771 M48t59State *s = &d->state;
772 Error *err = NULL;
774 s->model = u->info.model;
775 s->size = u->info.size;
776 sysbus_init_irq(dev, &s->IRQ);
778 memory_region_init_io(&s->iomem, o, &nvram_ops, s, "m48t59.nvram",
779 s->size);
780 memory_region_init_io(&d->io, o, &m48t59_io_ops, s, "m48t59", 4);
781 sysbus_init_mmio(dev, &s->iomem);
782 sysbus_init_mmio(dev, &d->io);
783 m48t59_realize_common(s, &err);
784 if (err != NULL) {
785 error_free(err);
786 return -1;
789 return 0;
792 static uint32_t m48txx_isa_read(Nvram *obj, uint32_t addr)
794 M48txxISAState *d = M48TXX_ISA(obj);
795 return m48t59_read(&d->state, addr);
798 static void m48txx_isa_write(Nvram *obj, uint32_t addr, uint32_t val)
800 M48txxISAState *d = M48TXX_ISA(obj);
801 m48t59_write(&d->state, addr, val);
804 static void m48txx_isa_toggle_lock(Nvram *obj, int lock)
806 M48txxISAState *d = M48TXX_ISA(obj);
807 m48t59_toggle_lock(&d->state, lock);
810 static Property m48t59_isa_properties[] = {
811 DEFINE_PROP_INT32("base-year", M48txxISAState, state.base_year, 0),
812 DEFINE_PROP_UINT32("iobase", M48txxISAState, io_base, 0x74),
813 DEFINE_PROP_END_OF_LIST(),
816 static void m48txx_isa_class_init(ObjectClass *klass, void *data)
818 DeviceClass *dc = DEVICE_CLASS(klass);
819 NvramClass *nc = NVRAM_CLASS(klass);
821 dc->realize = m48t59_isa_realize;
822 dc->reset = m48t59_reset_isa;
823 dc->props = m48t59_isa_properties;
824 nc->read = m48txx_isa_read;
825 nc->write = m48txx_isa_write;
826 nc->toggle_lock = m48txx_isa_toggle_lock;
829 static void m48txx_isa_concrete_class_init(ObjectClass *klass, void *data)
831 M48txxISADeviceClass *u = M48TXX_ISA_CLASS(klass);
832 M48txxInfo *info = data;
834 u->info = *info;
837 static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr)
839 M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
840 return m48t59_read(&d->state, addr);
843 static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val)
845 M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
846 m48t59_write(&d->state, addr, val);
849 static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock)
851 M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
852 m48t59_toggle_lock(&d->state, lock);
855 static Property m48t59_sysbus_properties[] = {
856 DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0),
857 DEFINE_PROP_END_OF_LIST(),
860 static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
862 DeviceClass *dc = DEVICE_CLASS(klass);
863 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
864 NvramClass *nc = NVRAM_CLASS(klass);
866 k->init = m48t59_init1;
867 dc->reset = m48t59_reset_sysbus;
868 dc->props = m48t59_sysbus_properties;
869 nc->read = m48txx_sysbus_read;
870 nc->write = m48txx_sysbus_write;
871 nc->toggle_lock = m48txx_sysbus_toggle_lock;
874 static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data)
876 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
877 M48txxInfo *info = data;
879 u->info = *info;
882 static const TypeInfo nvram_info = {
883 .name = TYPE_NVRAM,
884 .parent = TYPE_INTERFACE,
885 .class_size = sizeof(NvramClass),
888 static const TypeInfo m48txx_sysbus_type_info = {
889 .name = TYPE_M48TXX_SYS_BUS,
890 .parent = TYPE_SYS_BUS_DEVICE,
891 .instance_size = sizeof(M48txxSysBusState),
892 .abstract = true,
893 .class_init = m48txx_sysbus_class_init,
894 .interfaces = (InterfaceInfo[]) {
895 { TYPE_NVRAM },
900 static const TypeInfo m48txx_isa_type_info = {
901 .name = TYPE_M48TXX_ISA,
902 .parent = TYPE_ISA_DEVICE,
903 .instance_size = sizeof(M48txxISAState),
904 .abstract = true,
905 .class_init = m48txx_isa_class_init,
906 .interfaces = (InterfaceInfo[]) {
907 { TYPE_NVRAM },
912 static void m48t59_register_types(void)
914 TypeInfo sysbus_type_info = {
915 .parent = TYPE_M48TXX_SYS_BUS,
916 .class_size = sizeof(M48txxSysBusDeviceClass),
917 .class_init = m48txx_sysbus_concrete_class_init,
919 TypeInfo isa_type_info = {
920 .parent = TYPE_M48TXX_ISA,
921 .class_size = sizeof(M48txxISADeviceClass),
922 .class_init = m48txx_isa_concrete_class_init,
924 int i;
926 type_register_static(&nvram_info);
927 type_register_static(&m48txx_sysbus_type_info);
928 type_register_static(&m48txx_isa_type_info);
930 for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
931 if (m48txx_info[i].sysbus_name) {
932 sysbus_type_info.name = m48txx_info[i].sysbus_name;
933 sysbus_type_info.class_data = &m48txx_info[i];
934 type_register(&sysbus_type_info);
937 if (m48txx_info[i].isa_name) {
938 isa_type_info.name = m48txx_info[i].isa_name;
939 isa_type_info.class_data = &m48txx_info[i];
940 type_register(&isa_type_info);
945 type_init(m48t59_register_types)