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_SQWE 0x08 58#define REG_B_DM 0x04 59 60#define REG_C_UF 0x10 61#define REG_C_IRQF 0x80 62#define REG_C_PF 0x40 63#define REG_C_AF 0x20 64 65struct RTCState { 66 uint8_t cmos_data[128]; 67 uint8_t cmos_index; 68 struct tm current_tm; 69 int base_year; 70 qemu_irq irq; 71 qemu_irq sqw_irq; 72 int it_shift; 73 /* periodic timer */ 74 QEMUTimer *periodic_timer; 75 int64_t next_periodic_time; 76 /* second update */ 77 int64_t next_second_time; 78#ifdef TARGET_I386 79 uint32_t irq_coalesced; 80 uint32_t period; 81 QEMUTimer *coalesced_timer; 82#endif 83 QEMUTimer *second_timer; 84 QEMUTimer *second_timer2; 85}; 86 87static void rtc_irq_raise(qemu_irq irq) { 88 /* When HPET is operating in legacy mode, RTC interrupts are disabled 89 * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy 90 * mode is established while interrupt is raised. We want it to 91 * be lowered in any case 92 */ 93#ifndef CONFIG_ANDROID 94#if defined TARGET_I386 || defined TARGET_X86_64 95 if (!hpet_in_legacy_mode()) 96#endif 97#endif 98 qemu_irq_raise(irq); 99} 100 101static void rtc_set_time(RTCState *s); 102static void rtc_copy_date(RTCState *s); 103 104#ifdef TARGET_I386 105static void rtc_coalesced_timer_update(RTCState *s) 106{ 107 if (s->irq_coalesced == 0) { 108 qemu_del_timer(s->coalesced_timer); 109 } else { 110 /* divide each RTC interval to 2 - 8 smaller intervals */ 111 int c = MIN(s->irq_coalesced, 7) + 1; 112 int64_t next_clock = qemu_get_clock_ns(vm_clock) + 113 muldiv64(s->period / c, get_ticks_per_sec(), 32768); 114 qemu_mod_timer(s->coalesced_timer, next_clock); 115 } 116} 117 118static void rtc_coalesced_timer(void *opaque) 119{ 120 RTCState *s = opaque; 121 122 if (s->irq_coalesced != 0) { 123 apic_reset_irq_delivered(); 124 s->cmos_data[RTC_REG_C] |= 0xc0; 125 rtc_irq_raise(s->irq); 126 if (apic_get_irq_delivered()) { 127 s->irq_coalesced--; 128 } 129 } 130 131 rtc_coalesced_timer_update(s); 132} 133#endif 134 135static void rtc_timer_update(RTCState *s, int64_t current_time) 136{ 137 int period_code, period; 138 int64_t cur_clock, next_irq_clock; 139 int enable_pie; 140 141 period_code = s->cmos_data[RTC_REG_A] & 0x0f; 142#ifndef CONFIG_ANDROID 143#if defined TARGET_I386 || defined TARGET_X86_64 144 /* disable periodic timer if hpet is in legacy mode, since interrupts are 145 * disabled anyway. 146 */ 147 enable_pie = !hpet_in_legacy_mode(); 148#else 149 enable_pie = 1; 150#endif 151#endif 152 enable_pie = 1; 153 154 if (period_code != 0 155 && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie) 156 || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) { 157 if (period_code <= 2) 158 period_code += 7; 159 /* period in 32 Khz cycles */ 160 period = 1 << (period_code - 1); 161#ifdef TARGET_I386 162 if(period != s->period) 163 s->irq_coalesced = (s->irq_coalesced * s->period) / period; 164 s->period = period; 165#endif 166 /* compute 32 khz clock */ 167 cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec()); 168 next_irq_clock = (cur_clock & ~(period - 1)) + period; 169 s->next_periodic_time = muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1; 170 qemu_mod_timer(s->periodic_timer, s->next_periodic_time); 171 } else { 172#ifdef TARGET_I386 173 s->irq_coalesced = 0; 174#endif 175 qemu_del_timer(s->periodic_timer); 176 } 177} 178 179static void rtc_periodic_timer(void *opaque) 180{ 181 RTCState *s = opaque; 182 183 rtc_timer_update(s, s->next_periodic_time); 184 if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { 185 s->cmos_data[RTC_REG_C] |= 0xc0; 186#ifdef TARGET_I386 187 if(rtc_td_hack) { 188 apic_reset_irq_delivered(); 189 rtc_irq_raise(s->irq); 190 if (!apic_get_irq_delivered()) { 191 s->irq_coalesced++; 192 rtc_coalesced_timer_update(s); 193 } 194 } else 195#endif 196 rtc_irq_raise(s->irq); 197 } 198 if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) { 199 /* Not square wave at all but we don't want 2048Hz interrupts! 200 Must be seen as a pulse. */ 201 qemu_irq_raise(s->sqw_irq); 202 } 203} 204 205static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) 206{ 207 RTCState *s = opaque; 208 209 if ((addr & 1) == 0) { 210 s->cmos_index = data & 0x7f; 211 } else { 212#ifdef DEBUG_CMOS 213 printf("cmos: write index=0x%02x val=0x%02x\n", 214 s->cmos_index, data); 215#endif 216 switch(s->cmos_index) { 217 case RTC_SECONDS_ALARM: 218 case RTC_MINUTES_ALARM: 219 case RTC_HOURS_ALARM: 220 /* XXX: not supported */ 221 s->cmos_data[s->cmos_index] = data; 222 break; 223 case RTC_SECONDS: 224 case RTC_MINUTES: 225 case RTC_HOURS: 226 case RTC_DAY_OF_WEEK: 227 case RTC_DAY_OF_MONTH: 228 case RTC_MONTH: 229 case RTC_YEAR: 230 s->cmos_data[s->cmos_index] = data; 231 /* if in set mode, do not update the time */ 232 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { 233 rtc_set_time(s); 234 } 235 break; 236 case RTC_REG_A: 237 /* UIP bit is read only */ 238 s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | 239 (s->cmos_data[RTC_REG_A] & REG_A_UIP); 240 rtc_timer_update(s, qemu_get_clock_ns(vm_clock)); 241 break; 242 case RTC_REG_B: 243 if (data & REG_B_SET) { 244 /* set mode: reset UIP mode */ 245 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; 246 data &= ~REG_B_UIE; 247 } else { 248 /* if disabling set mode, update the time */ 249 if (s->cmos_data[RTC_REG_B] & REG_B_SET) { 250 rtc_set_time(s); 251 } 252 } 253 s->cmos_data[RTC_REG_B] = data; 254 rtc_timer_update(s, qemu_get_clock_ns(vm_clock)); 255 break; 256 case RTC_REG_C: 257 case RTC_REG_D: 258 /* cannot write to them */ 259 break; 260 default: 261 s->cmos_data[s->cmos_index] = data; 262 break; 263 } 264 } 265} 266 267static inline int rtc_to_bcd(RTCState *s, int a) 268{ 269 if (s->cmos_data[RTC_REG_B] & REG_B_DM) { 270 return a; 271 } else { 272 return ((a / 10) << 4) | (a % 10); 273 } 274} 275 276static inline int rtc_from_bcd(RTCState *s, int a) 277{ 278 if (s->cmos_data[RTC_REG_B] & REG_B_DM) { 279 return a; 280 } else { 281 return ((a >> 4) * 10) + (a & 0x0f); 282 } 283} 284 285static void rtc_set_time(RTCState *s) 286{ 287 struct tm *tm = &s->current_tm; 288 289 tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); 290 tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); 291 tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); 292 if (!(s->cmos_data[RTC_REG_B] & 0x02) && 293 (s->cmos_data[RTC_HOURS] & 0x80)) { 294 tm->tm_hour += 12; 295 } 296 tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1; 297 tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); 298 tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; 299 tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; 300} 301 302static void rtc_copy_date(RTCState *s) 303{ 304 const struct tm *tm = &s->current_tm; 305 int year; 306 307 s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec); 308 s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min); 309 if (s->cmos_data[RTC_REG_B] & 0x02) { 310 /* 24 hour format */ 311 s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour); 312 } else { 313 /* 12 hour format */ 314 s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour % 12); 315 if (tm->tm_hour >= 12) 316 s->cmos_data[RTC_HOURS] |= 0x80; 317 } 318 s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1); 319 s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday); 320 s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1); 321 year = (tm->tm_year - s->base_year) % 100; 322 if (year < 0) 323 year += 100; 324 s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year); 325} 326 327/* month is between 0 and 11. */ 328static int get_days_in_month(int month, int year) 329{ 330 static const int days_tab[12] = { 331 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 332 }; 333 int d; 334 if ((unsigned )month >= 12) 335 return 31; 336 d = days_tab[month]; 337 if (month == 1) { 338 if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) 339 d++; 340 } 341 return d; 342} 343 344/* update 'tm' to the next second */ 345static void rtc_next_second(struct tm *tm) 346{ 347 int days_in_month; 348 349 tm->tm_sec++; 350 if ((unsigned)tm->tm_sec >= 60) { 351 tm->tm_sec = 0; 352 tm->tm_min++; 353 if ((unsigned)tm->tm_min >= 60) { 354 tm->tm_min = 0; 355 tm->tm_hour++; 356 if ((unsigned)tm->tm_hour >= 24) { 357 tm->tm_hour = 0; 358 /* next day */ 359 tm->tm_wday++; 360 if ((unsigned)tm->tm_wday >= 7) 361 tm->tm_wday = 0; 362 days_in_month = get_days_in_month(tm->tm_mon, 363 tm->tm_year + 1900); 364 tm->tm_mday++; 365 if (tm->tm_mday < 1) { 366 tm->tm_mday = 1; 367 } else if (tm->tm_mday > days_in_month) { 368 tm->tm_mday = 1; 369 tm->tm_mon++; 370 if (tm->tm_mon >= 12) { 371 tm->tm_mon = 0; 372 tm->tm_year++; 373 } 374 } 375 } 376 } 377 } 378} 379 380 381static void rtc_update_second(void *opaque) 382{ 383 RTCState *s = opaque; 384 int64_t delay; 385 386 /* if the oscillator is not in normal operation, we do not update */ 387 if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) { 388 s->next_second_time += get_ticks_per_sec(); 389 qemu_mod_timer(s->second_timer, s->next_second_time); 390 } else { 391 rtc_next_second(&s->current_tm); 392 393 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { 394 /* update in progress bit */ 395 s->cmos_data[RTC_REG_A] |= REG_A_UIP; 396 } 397 /* should be 244 us = 8 / 32768 seconds, but currently the 398 timers do not have the necessary resolution. */ 399 delay = (get_ticks_per_sec() * 1) / 100; 400 if (delay < 1) 401 delay = 1; 402 qemu_mod_timer(s->second_timer2, 403 s->next_second_time + delay); 404 } 405} 406 407static void rtc_update_second2(void *opaque) 408{ 409 RTCState *s = opaque; 410 411 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { 412 rtc_copy_date(s); 413 } 414 415 /* check alarm */ 416 if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { 417 if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || 418 s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) && 419 ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || 420 s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) && 421 ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || 422 s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) { 423 424 s->cmos_data[RTC_REG_C] |= 0xa0; 425 rtc_irq_raise(s->irq); 426 } 427 } 428 429 /* update ended interrupt */ 430 if (s->cmos_data[RTC_REG_B] & REG_B_UIE) { 431 s->cmos_data[RTC_REG_C] |= 0x90; 432 rtc_irq_raise(s->irq); 433 } 434 435 /* clear update in progress bit */ 436 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; 437 438 s->next_second_time += get_ticks_per_sec(); 439 qemu_mod_timer(s->second_timer, s->next_second_time); 440} 441 442static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) 443{ 444 RTCState *s = opaque; 445 int ret; 446 if ((addr & 1) == 0) { 447 return 0xff; 448 } else { 449 switch(s->cmos_index) { 450 case RTC_SECONDS: 451 case RTC_MINUTES: 452 case RTC_HOURS: 453 case RTC_DAY_OF_WEEK: 454 case RTC_DAY_OF_MONTH: 455 case RTC_MONTH: 456 case RTC_YEAR: 457 ret = s->cmos_data[s->cmos_index]; 458 break; 459 case RTC_REG_A: 460 ret = s->cmos_data[s->cmos_index]; 461 break; 462 case RTC_REG_C: 463 ret = s->cmos_data[s->cmos_index]; 464 qemu_irq_lower(s->irq); 465 s->cmos_data[RTC_REG_C] = 0x00; 466 break; 467 default: 468 ret = s->cmos_data[s->cmos_index]; 469 break; 470 } 471#ifdef DEBUG_CMOS 472 printf("cmos: read index=0x%02x val=0x%02x\n", 473 s->cmos_index, ret); 474#endif 475 return ret; 476 } 477} 478 479void rtc_set_memory(RTCState *s, int addr, int val) 480{ 481 if (addr >= 0 && addr <= 127) 482 s->cmos_data[addr] = val; 483} 484 485void rtc_set_date(RTCState *s, const struct tm *tm) 486{ 487 s->current_tm = *tm; 488 rtc_copy_date(s); 489} 490 491/* PC cmos mappings */ 492#define REG_IBM_CENTURY_BYTE 0x32 493#define REG_IBM_PS2_CENTURY_BYTE 0x37 494 495static void rtc_set_date_from_host(RTCState *s) 496{ 497 struct tm tm; 498 int val; 499 500 /* set the CMOS date */ 501 qemu_get_timedate(&tm, 0); 502 rtc_set_date(s, &tm); 503 504 val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); 505 rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val); 506 rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val); 507} 508 509static void rtc_save(QEMUFile *f, void *opaque) 510{ 511 RTCState *s = opaque; 512 513 qemu_put_buffer(f, s->cmos_data, 128); 514 qemu_put_8s(f, &s->cmos_index); 515 516 qemu_put_be32(f, s->current_tm.tm_sec); 517 qemu_put_be32(f, s->current_tm.tm_min); 518 qemu_put_be32(f, s->current_tm.tm_hour); 519 qemu_put_be32(f, s->current_tm.tm_wday); 520 qemu_put_be32(f, s->current_tm.tm_mday); 521 qemu_put_be32(f, s->current_tm.tm_mon); 522 qemu_put_be32(f, s->current_tm.tm_year); 523 524 qemu_put_timer(f, s->periodic_timer); 525 qemu_put_be64(f, s->next_periodic_time); 526 527 qemu_put_be64(f, s->next_second_time); 528 qemu_put_timer(f, s->second_timer); 529 qemu_put_timer(f, s->second_timer2); 530} 531 532static int rtc_load(QEMUFile *f, void *opaque, int version_id) 533{ 534 RTCState *s = opaque; 535 536 if (version_id != 1) 537 return -EINVAL; 538 539 qemu_get_buffer(f, s->cmos_data, 128); 540 qemu_get_8s(f, &s->cmos_index); 541 542 s->current_tm.tm_sec=qemu_get_be32(f); 543 s->current_tm.tm_min=qemu_get_be32(f); 544 s->current_tm.tm_hour=qemu_get_be32(f); 545 s->current_tm.tm_wday=qemu_get_be32(f); 546 s->current_tm.tm_mday=qemu_get_be32(f); 547 s->current_tm.tm_mon=qemu_get_be32(f); 548 s->current_tm.tm_year=qemu_get_be32(f); 549 550 qemu_get_timer(f, s->periodic_timer); 551 s->next_periodic_time=qemu_get_be64(f); 552 553 s->next_second_time=qemu_get_be64(f); 554 qemu_get_timer(f, s->second_timer); 555 qemu_get_timer(f, s->second_timer2); 556 return 0; 557} 558 559#ifdef TARGET_I386 560static void rtc_save_td(QEMUFile *f, void *opaque) 561{ 562 RTCState *s = opaque; 563 564 qemu_put_be32(f, s->irq_coalesced); 565 qemu_put_be32(f, s->period); 566} 567 568static int rtc_load_td(QEMUFile *f, void *opaque, int version_id) 569{ 570 RTCState *s = opaque; 571 572 if (version_id != 1) 573 return -EINVAL; 574 575 s->irq_coalesced = qemu_get_be32(f); 576 s->period = qemu_get_be32(f); 577 rtc_coalesced_timer_update(s); 578 return 0; 579} 580#endif 581 582static void rtc_reset(void *opaque) 583{ 584 RTCState *s = opaque; 585 586 s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE); 587 s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF); 588 589 qemu_irq_lower(s->irq); 590 591#ifdef TARGET_I386 592 if (rtc_td_hack) 593 s->irq_coalesced = 0; 594#endif 595} 596 597RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year) 598{ 599 RTCState *s; 600 601 s = qemu_mallocz(sizeof(RTCState)); 602 603 s->irq = irq; 604 s->sqw_irq = sqw_irq; 605 s->cmos_data[RTC_REG_A] = 0x26; 606 s->cmos_data[RTC_REG_B] = 0x02; 607 s->cmos_data[RTC_REG_C] = 0x00; 608 s->cmos_data[RTC_REG_D] = 0x80; 609 610 s->base_year = base_year; 611 rtc_set_date_from_host(s); 612 613 s->periodic_timer = qemu_new_timer_ns(vm_clock, 614 rtc_periodic_timer, s); 615#ifdef TARGET_I386 616 if (rtc_td_hack) 617 s->coalesced_timer = qemu_new_timer_ns(vm_clock, rtc_coalesced_timer, s); 618#endif 619 s->second_timer = qemu_new_timer_ns(vm_clock, 620 rtc_update_second, s); 621 s->second_timer2 = qemu_new_timer_ns(vm_clock, 622 rtc_update_second2, s); 623 624 s->next_second_time = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() * 99) / 100; 625 qemu_mod_timer(s->second_timer2, s->next_second_time); 626 627 register_ioport_write(base, 2, 1, cmos_ioport_write, s); 628 register_ioport_read(base, 2, 1, cmos_ioport_read, s); 629 630 register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); 631#ifdef TARGET_I386 632 if (rtc_td_hack) 633 register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s); 634#endif 635 qemu_register_reset(rtc_reset, 0, s); 636 637 return s; 638} 639 640RTCState *rtc_init(int base, qemu_irq irq, int base_year) 641{ 642 return rtc_init_sqw(base, irq, NULL, base_year); 643} 644 645/* Memory mapped interface */ 646static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr) 647{ 648 RTCState *s = opaque; 649 650 return cmos_ioport_read(s, addr >> s->it_shift) & 0xFF; 651} 652 653static void cmos_mm_writeb (void *opaque, 654 target_phys_addr_t addr, uint32_t value) 655{ 656 RTCState *s = opaque; 657 658 cmos_ioport_write(s, addr >> s->it_shift, value & 0xFF); 659} 660 661static uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr) 662{ 663 RTCState *s = opaque; 664 uint32_t val; 665 666 val = cmos_ioport_read(s, addr >> s->it_shift) & 0xFFFF; 667#ifdef TARGET_WORDS_BIGENDIAN 668 val = bswap16(val); 669#endif 670 return val; 671} 672 673static void cmos_mm_writew (void *opaque, 674 target_phys_addr_t addr, uint32_t value) 675{ 676 RTCState *s = opaque; 677#ifdef TARGET_WORDS_BIGENDIAN 678 value = bswap16(value); 679#endif 680 cmos_ioport_write(s, addr >> s->it_shift, value & 0xFFFF); 681} 682 683static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr) 684{ 685 RTCState *s = opaque; 686 uint32_t val; 687 688 val = cmos_ioport_read(s, addr >> s->it_shift); 689#ifdef TARGET_WORDS_BIGENDIAN 690 val = bswap32(val); 691#endif 692 return val; 693} 694 695static void cmos_mm_writel (void *opaque, 696 target_phys_addr_t addr, uint32_t value) 697{ 698 RTCState *s = opaque; 699#ifdef TARGET_WORDS_BIGENDIAN 700 value = bswap32(value); 701#endif 702 cmos_ioport_write(s, addr >> s->it_shift, value); 703} 704 705static CPUReadMemoryFunc *rtc_mm_read[] = { 706 &cmos_mm_readb, 707 &cmos_mm_readw, 708 &cmos_mm_readl, 709}; 710 711static CPUWriteMemoryFunc *rtc_mm_write[] = { 712 &cmos_mm_writeb, 713 &cmos_mm_writew, 714 &cmos_mm_writel, 715}; 716 717RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, 718 int base_year) 719{ 720 RTCState *s; 721 int io_memory; 722 723 s = qemu_mallocz(sizeof(RTCState)); 724 725 s->irq = irq; 726 s->cmos_data[RTC_REG_A] = 0x26; 727 s->cmos_data[RTC_REG_B] = 0x02; 728 s->cmos_data[RTC_REG_C] = 0x00; 729 s->cmos_data[RTC_REG_D] = 0x80; 730 731 s->base_year = base_year; 732 rtc_set_date_from_host(s); 733 734 s->periodic_timer = qemu_new_timer_ns(vm_clock, 735 rtc_periodic_timer, s); 736 s->second_timer = qemu_new_timer_ns(vm_clock, 737 rtc_update_second, s); 738 s->second_timer2 = qemu_new_timer_ns(vm_clock, 739 rtc_update_second2, s); 740 741 s->next_second_time = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() * 99) / 100; 742 qemu_mod_timer(s->second_timer2, s->next_second_time); 743 744 io_memory = cpu_register_io_memory(rtc_mm_read, rtc_mm_write, s); 745 cpu_register_physical_memory(base, 2 << it_shift, io_memory); 746 747 register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); 748#ifdef TARGET_I386 749 if (rtc_td_hack) 750 register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s); 751#endif 752 qemu_register_reset(rtc_reset, 0, s); 753 return s; 754} 755