Statistics
| Branch: | Revision:

root / hw / mc146818rtc.c @ 5703c174

History | View | Annotate | Download (17.5 kB)

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
#include "hpet_emul.h"
30

    
31
//#define DEBUG_CMOS
32

    
33
#define RTC_SECONDS             0
34
#define RTC_SECONDS_ALARM       1
35
#define RTC_MINUTES             2
36
#define RTC_MINUTES_ALARM       3
37
#define RTC_HOURS               4
38
#define RTC_HOURS_ALARM         5
39
#define RTC_ALARM_DONT_CARE    0xC0
40

    
41
#define RTC_DAY_OF_WEEK         6
42
#define RTC_DAY_OF_MONTH        7
43
#define RTC_MONTH               8
44
#define RTC_YEAR                9
45

    
46
#define RTC_REG_A               10
47
#define RTC_REG_B               11
48
#define RTC_REG_C               12
49
#define RTC_REG_D               13
50

    
51
#define REG_A_UIP 0x80
52

    
53
#define REG_B_SET 0x80
54
#define REG_B_PIE 0x40
55
#define REG_B_AIE 0x20
56
#define REG_B_UIE 0x10
57
#define REG_B_DM  0x04
58

    
59
struct RTCState {
60
    uint8_t cmos_data[128];
61
    uint8_t cmos_index;
62
    struct tm current_tm;
63
    qemu_irq irq;
64
    int it_shift;
65
    /* periodic timer */
66
    QEMUTimer *periodic_timer;
67
    int64_t next_periodic_time;
68
    /* second update */
69
    int64_t next_second_time;
70
    QEMUTimer *second_timer;
71
    QEMUTimer *second_timer2;
72
};
73

    
74
static void rtc_irq_raise(qemu_irq irq) {
75
    /* When HPET is operating in legacy mode, RTC interrupts are disabled
76
     * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
77
     * mode is established while interrupt is raised. We want it to
78
     * be lowered in any case
79
     */
80
#if defined TARGET_I386 || defined TARGET_X86_64
81
    if (!hpet_in_legacy_mode())
82
#endif
83
        qemu_irq_raise(irq);
84
}
85

    
86
static void rtc_set_time(RTCState *s);
87
static void rtc_copy_date(RTCState *s);
88

    
89
static void rtc_timer_update(RTCState *s, int64_t current_time)
90
{
91
    int period_code, period;
92
    int64_t cur_clock, next_irq_clock;
93

    
94
    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
95
#if defined TARGET_I386 || defined TARGET_X86_64
96
    /* disable periodic timer if hpet is in legacy mode, since interrupts are
97
     * disabled anyway.
98
     */
99
    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
100
#else
101
    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
102
#endif
103
        if (period_code <= 2)
104
            period_code += 7;
105
        /* period in 32 Khz cycles */
106
        period = 1 << (period_code - 1);
107
        /* compute 32 khz clock */
108
        cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
109
        next_irq_clock = (cur_clock & ~(period - 1)) + period;
110
        s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
111
        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
112
    } else {
113
        qemu_del_timer(s->periodic_timer);
114
    }
115
}
116

    
117
static void rtc_periodic_timer(void *opaque)
118
{
119
    RTCState *s = opaque;
120

    
121
    rtc_timer_update(s, s->next_periodic_time);
122
    s->cmos_data[RTC_REG_C] |= 0xc0;
123
    rtc_irq_raise(s->irq);
124
}
125

    
126
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
127
{
128
    RTCState *s = opaque;
129

    
130
    if ((addr & 1) == 0) {
131
        s->cmos_index = data & 0x7f;
132
    } else {
133
#ifdef DEBUG_CMOS
134
        printf("cmos: write index=0x%02x val=0x%02x\n",
135
               s->cmos_index, data);
136
#endif
137
        switch(s->cmos_index) {
138
        case RTC_SECONDS_ALARM:
139
        case RTC_MINUTES_ALARM:
140
        case RTC_HOURS_ALARM:
141
            /* XXX: not supported */
142
            s->cmos_data[s->cmos_index] = data;
143
            break;
144
        case RTC_SECONDS:
145
        case RTC_MINUTES:
146
        case RTC_HOURS:
147
        case RTC_DAY_OF_WEEK:
148
        case RTC_DAY_OF_MONTH:
149
        case RTC_MONTH:
150
        case RTC_YEAR:
151
            s->cmos_data[s->cmos_index] = data;
152
            /* if in set mode, do not update the time */
153
            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
154
                rtc_set_time(s);
155
            }
156
            break;
157
        case RTC_REG_A:
158
            /* UIP bit is read only */
159
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
160
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
161
            rtc_timer_update(s, qemu_get_clock(vm_clock));
162
            break;
163
        case RTC_REG_B:
164
            if (data & REG_B_SET) {
165
                /* set mode: reset UIP mode */
166
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
167
                data &= ~REG_B_UIE;
168
            } else {
169
                /* if disabling set mode, update the time */
170
                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
171
                    rtc_set_time(s);
172
                }
173
            }
174
            s->cmos_data[RTC_REG_B] = data;
175
            rtc_timer_update(s, qemu_get_clock(vm_clock));
176
            break;
177
        case RTC_REG_C:
178
        case RTC_REG_D:
179
            /* cannot write to them */
180
            break;
181
        default:
182
            s->cmos_data[s->cmos_index] = data;
183
            break;
184
        }
185
    }
186
}
187

    
188
static inline int to_bcd(RTCState *s, int a)
189
{
190
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
191
        return a;
192
    } else {
193
        return ((a / 10) << 4) | (a % 10);
194
    }
195
}
196

    
197
static inline int from_bcd(RTCState *s, int a)
198
{
199
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
200
        return a;
201
    } else {
202
        return ((a >> 4) * 10) + (a & 0x0f);
203
    }
204
}
205

    
206
static void rtc_set_time(RTCState *s)
207
{
208
    struct tm *tm = &s->current_tm;
209

    
210
    tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
211
    tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
212
    tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
213
    if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
214
        (s->cmos_data[RTC_HOURS] & 0x80)) {
215
        tm->tm_hour += 12;
216
    }
217
    tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
218
    tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
219
    tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
220
    tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
221
}
222

    
223
static void rtc_copy_date(RTCState *s)
224
{
225
    const struct tm *tm = &s->current_tm;
226

    
227
    s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
228
    s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
229
    if (s->cmos_data[RTC_REG_B] & 0x02) {
230
        /* 24 hour format */
231
        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
232
    } else {
233
        /* 12 hour format */
234
        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
235
        if (tm->tm_hour >= 12)
236
            s->cmos_data[RTC_HOURS] |= 0x80;
237
    }
238
    s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday + 1);
239
    s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
240
    s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
241
    s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
242
}
243

    
244
/* month is between 0 and 11. */
245
static int get_days_in_month(int month, int year)
246
{
247
    static const int days_tab[12] = {
248
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
249
    };
250
    int d;
251
    if ((unsigned )month >= 12)
252
        return 31;
253
    d = days_tab[month];
254
    if (month == 1) {
255
        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
256
            d++;
257
    }
258
    return d;
259
}
260

    
261
/* update 'tm' to the next second */
262
static void rtc_next_second(struct tm *tm)
263
{
264
    int days_in_month;
265

    
266
    tm->tm_sec++;
267
    if ((unsigned)tm->tm_sec >= 60) {
268
        tm->tm_sec = 0;
269
        tm->tm_min++;
270
        if ((unsigned)tm->tm_min >= 60) {
271
            tm->tm_min = 0;
272
            tm->tm_hour++;
273
            if ((unsigned)tm->tm_hour >= 24) {
274
                tm->tm_hour = 0;
275
                /* next day */
276
                tm->tm_wday++;
277
                if ((unsigned)tm->tm_wday >= 7)
278
                    tm->tm_wday = 0;
279
                days_in_month = get_days_in_month(tm->tm_mon,
280
                                                  tm->tm_year + 1900);
281
                tm->tm_mday++;
282
                if (tm->tm_mday < 1) {
283
                    tm->tm_mday = 1;
284
                } else if (tm->tm_mday > days_in_month) {
285
                    tm->tm_mday = 1;
286
                    tm->tm_mon++;
287
                    if (tm->tm_mon >= 12) {
288
                        tm->tm_mon = 0;
289
                        tm->tm_year++;
290
                    }
291
                }
292
            }
293
        }
294
    }
295
}
296

    
297

    
298
static void rtc_update_second(void *opaque)
299
{
300
    RTCState *s = opaque;
301
    int64_t delay;
302

    
303
    /* if the oscillator is not in normal operation, we do not update */
304
    if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
305
        s->next_second_time += ticks_per_sec;
306
        qemu_mod_timer(s->second_timer, s->next_second_time);
307
    } else {
308
        rtc_next_second(&s->current_tm);
309

    
310
        if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
311
            /* update in progress bit */
312
            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
313
        }
314
        /* should be 244 us = 8 / 32768 seconds, but currently the
315
           timers do not have the necessary resolution. */
316
        delay = (ticks_per_sec * 1) / 100;
317
        if (delay < 1)
318
            delay = 1;
319
        qemu_mod_timer(s->second_timer2,
320
                       s->next_second_time + delay);
321
    }
322
}
323

    
324
static void rtc_update_second2(void *opaque)
325
{
326
    RTCState *s = opaque;
327

    
328
    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
329
        rtc_copy_date(s);
330
    }
331

    
332
    /* check alarm */
333
    if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
334
        if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
335
             s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
336
            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
337
             s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
338
            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
339
             s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
340

    
341
            s->cmos_data[RTC_REG_C] |= 0xa0;
342
            rtc_irq_raise(s->irq);
343
        }
344
    }
345

    
346
    /* update ended interrupt */
347
    if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
348
        s->cmos_data[RTC_REG_C] |= 0x90;
349
        rtc_irq_raise(s->irq);
350
    }
351

    
352
    /* clear update in progress bit */
353
    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
354

    
355
    s->next_second_time += ticks_per_sec;
356
    qemu_mod_timer(s->second_timer, s->next_second_time);
357
}
358

    
359
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
360
{
361
    RTCState *s = opaque;
362
    int ret;
363
    if ((addr & 1) == 0) {
364
        return 0xff;
365
    } else {
366
        switch(s->cmos_index) {
367
        case RTC_SECONDS:
368
        case RTC_MINUTES:
369
        case RTC_HOURS:
370
        case RTC_DAY_OF_WEEK:
371
        case RTC_DAY_OF_MONTH:
372
        case RTC_MONTH:
373
        case RTC_YEAR:
374
            ret = s->cmos_data[s->cmos_index];
375
            break;
376
        case RTC_REG_A:
377
            ret = s->cmos_data[s->cmos_index];
378
            break;
379
        case RTC_REG_C:
380
            ret = s->cmos_data[s->cmos_index];
381
            qemu_irq_lower(s->irq);
382
            s->cmos_data[RTC_REG_C] = 0x00;
383
            break;
384
        default:
385
            ret = s->cmos_data[s->cmos_index];
386
            break;
387
        }
388
#ifdef DEBUG_CMOS
389
        printf("cmos: read index=0x%02x val=0x%02x\n",
390
               s->cmos_index, ret);
391
#endif
392
        return ret;
393
    }
394
}
395

    
396
void rtc_set_memory(RTCState *s, int addr, int val)
397
{
398
    if (addr >= 0 && addr <= 127)
399
        s->cmos_data[addr] = val;
400
}
401

    
402
void rtc_set_date(RTCState *s, const struct tm *tm)
403
{
404
    s->current_tm = *tm;
405
    rtc_copy_date(s);
406
}
407

    
408
/* PC cmos mappings */
409
#define REG_IBM_CENTURY_BYTE        0x32
410
#define REG_IBM_PS2_CENTURY_BYTE    0x37
411

    
412
static void rtc_set_date_from_host(RTCState *s)
413
{
414
    struct tm tm;
415
    int val;
416

    
417
    /* set the CMOS date */
418
    qemu_get_timedate(&tm, 0);
419
    rtc_set_date(s, &tm);
420

    
421
    val = to_bcd(s, (tm.tm_year / 100) + 19);
422
    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
423
    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
424
}
425

    
426
static void rtc_save(QEMUFile *f, void *opaque)
427
{
428
    RTCState *s = opaque;
429

    
430
    qemu_put_buffer(f, s->cmos_data, 128);
431
    qemu_put_8s(f, &s->cmos_index);
432

    
433
    qemu_put_be32(f, s->current_tm.tm_sec);
434
    qemu_put_be32(f, s->current_tm.tm_min);
435
    qemu_put_be32(f, s->current_tm.tm_hour);
436
    qemu_put_be32(f, s->current_tm.tm_wday);
437
    qemu_put_be32(f, s->current_tm.tm_mday);
438
    qemu_put_be32(f, s->current_tm.tm_mon);
439
    qemu_put_be32(f, s->current_tm.tm_year);
440

    
441
    qemu_put_timer(f, s->periodic_timer);
442
    qemu_put_be64(f, s->next_periodic_time);
443

    
444
    qemu_put_be64(f, s->next_second_time);
445
    qemu_put_timer(f, s->second_timer);
446
    qemu_put_timer(f, s->second_timer2);
447
}
448

    
449
static int rtc_load(QEMUFile *f, void *opaque, int version_id)
450
{
451
    RTCState *s = opaque;
452

    
453
    if (version_id != 1)
454
        return -EINVAL;
455

    
456
    qemu_get_buffer(f, s->cmos_data, 128);
457
    qemu_get_8s(f, &s->cmos_index);
458

    
459
    s->current_tm.tm_sec=qemu_get_be32(f);
460
    s->current_tm.tm_min=qemu_get_be32(f);
461
    s->current_tm.tm_hour=qemu_get_be32(f);
462
    s->current_tm.tm_wday=qemu_get_be32(f);
463
    s->current_tm.tm_mday=qemu_get_be32(f);
464
    s->current_tm.tm_mon=qemu_get_be32(f);
465
    s->current_tm.tm_year=qemu_get_be32(f);
466

    
467
    qemu_get_timer(f, s->periodic_timer);
468
    s->next_periodic_time=qemu_get_be64(f);
469

    
470
    s->next_second_time=qemu_get_be64(f);
471
    qemu_get_timer(f, s->second_timer);
472
    qemu_get_timer(f, s->second_timer2);
473
    return 0;
474
}
475

    
476
RTCState *rtc_init(int base, qemu_irq irq)
477
{
478
    RTCState *s;
479

    
480
    s = qemu_mallocz(sizeof(RTCState));
481
    if (!s)
482
        return NULL;
483

    
484
    s->irq = irq;
485
    s->cmos_data[RTC_REG_A] = 0x26;
486
    s->cmos_data[RTC_REG_B] = 0x02;
487
    s->cmos_data[RTC_REG_C] = 0x00;
488
    s->cmos_data[RTC_REG_D] = 0x80;
489

    
490
    rtc_set_date_from_host(s);
491

    
492
    s->periodic_timer = qemu_new_timer(vm_clock,
493
                                       rtc_periodic_timer, s);
494
    s->second_timer = qemu_new_timer(vm_clock,
495
                                     rtc_update_second, s);
496
    s->second_timer2 = qemu_new_timer(vm_clock,
497
                                      rtc_update_second2, s);
498

    
499
    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
500
    qemu_mod_timer(s->second_timer2, s->next_second_time);
501

    
502
    register_ioport_write(base, 2, 1, cmos_ioport_write, s);
503
    register_ioport_read(base, 2, 1, cmos_ioport_read, s);
504

    
505
    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
506
    return s;
507
}
508

    
509
/* Memory mapped interface */
510
static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
511
{
512
    RTCState *s = opaque;
513

    
514
    return cmos_ioport_read(s, addr >> s->it_shift) & 0xFF;
515
}
516

    
517
static void cmos_mm_writeb (void *opaque,
518
                            target_phys_addr_t addr, uint32_t value)
519
{
520
    RTCState *s = opaque;
521

    
522
    cmos_ioport_write(s, addr >> s->it_shift, value & 0xFF);
523
}
524

    
525
static uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
526
{
527
    RTCState *s = opaque;
528
    uint32_t val;
529

    
530
    val = cmos_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
531
#ifdef TARGET_WORDS_BIGENDIAN
532
    val = bswap16(val);
533
#endif
534
    return val;
535
}
536

    
537
static void cmos_mm_writew (void *opaque,
538
                            target_phys_addr_t addr, uint32_t value)
539
{
540
    RTCState *s = opaque;
541
#ifdef TARGET_WORDS_BIGENDIAN
542
    value = bswap16(value);
543
#endif
544
    cmos_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
545
}
546

    
547
static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
548
{
549
    RTCState *s = opaque;
550
    uint32_t val;
551

    
552
    val = cmos_ioport_read(s, addr >> s->it_shift);
553
#ifdef TARGET_WORDS_BIGENDIAN
554
    val = bswap32(val);
555
#endif
556
    return val;
557
}
558

    
559
static void cmos_mm_writel (void *opaque,
560
                            target_phys_addr_t addr, uint32_t value)
561
{
562
    RTCState *s = opaque;
563
#ifdef TARGET_WORDS_BIGENDIAN
564
    value = bswap32(value);
565
#endif
566
    cmos_ioport_write(s, addr >> s->it_shift, value);
567
}
568

    
569
static CPUReadMemoryFunc *rtc_mm_read[] = {
570
    &cmos_mm_readb,
571
    &cmos_mm_readw,
572
    &cmos_mm_readl,
573
};
574

    
575
static CPUWriteMemoryFunc *rtc_mm_write[] = {
576
    &cmos_mm_writeb,
577
    &cmos_mm_writew,
578
    &cmos_mm_writel,
579
};
580

    
581
RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq)
582
{
583
    RTCState *s;
584
    int io_memory;
585

    
586
    s = qemu_mallocz(sizeof(RTCState));
587
    if (!s)
588
        return NULL;
589

    
590
    s->irq = irq;
591
    s->cmos_data[RTC_REG_A] = 0x26;
592
    s->cmos_data[RTC_REG_B] = 0x02;
593
    s->cmos_data[RTC_REG_C] = 0x00;
594
    s->cmos_data[RTC_REG_D] = 0x80;
595

    
596
    rtc_set_date_from_host(s);
597

    
598
    s->periodic_timer = qemu_new_timer(vm_clock,
599
                                       rtc_periodic_timer, s);
600
    s->second_timer = qemu_new_timer(vm_clock,
601
                                     rtc_update_second, s);
602
    s->second_timer2 = qemu_new_timer(vm_clock,
603
                                      rtc_update_second2, s);
604

    
605
    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
606
    qemu_mod_timer(s->second_timer2, s->next_second_time);
607

    
608
    io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
609
    cpu_register_physical_memory(base, 2 << it_shift, io_memory);
610

    
611
    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
612
    return s;
613
}