DevRTC.cpp revision 034f0367d3b0431c6346b1a3af3abb435ee50d4e
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * Motorola MC146818 RTC/CMOS Device.
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * available from http://www.virtualbox.org. This file is free software;
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * General Public License (GPL) as published by the Free Software
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * additional information or have any questions.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * --------------------------------------------------------------------
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * This code is based on:
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * QEMU MC146818 RTC emulation
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (c) 2003-2004 Fabrice Bellard
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * of this software and associated documentation files (the "Software"), to deal
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * in the Software without restriction, including without limitation the rights
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
ceea06560fe5d384c1ed7ed0f8d5b69504456fccvboxsync * copies of the Software, and to permit persons to whom the Software is
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * furnished to do so, subject to the following conditions:
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * The above copyright notice and this permission notice shall be included in
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * all copies or substantial portions of the Software.
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0a7b20727716a00270f358a1c546473d8c36e8f3vboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync * THE SOFTWARE.
3aad980b92149dd95a1ab72ddb8d11d61a28ace6vboxsync/*******************************************************************************
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync* Header Files *
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync*******************************************************************************/
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync#endif /* IN_RING3 */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/*******************************************************************************
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync* Internal Functions *
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync*******************************************************************************/
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncPDMBOTHCBDECL(int) rtcIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncPDMBOTHCBDECL(int) rtcIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncPDMBOTHCBDECL(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncPDMBOTHCBDECL(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncPDMBOTHCBDECL(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/*******************************************************************************
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync* Defined Constants And Macros *
d605d5391db09e6395a1c091f148f4b86af84bd3vboxsync*******************************************************************************/
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync/*#define DEBUG_CMOS*/
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/** The saved state version. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/** The saved state version used by VirtualBox 3.1 and earlier.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * This does not include disabled by HPET state. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/** The saved state version used by VirtualBox 3.0 and earlier.
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * This does not include the configuration. */
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync/*******************************************************************************
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync* Structures and Typedefs *
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync*******************************************************************************/
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync/** @todo Replace struct my_tm with RTTIME. */
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync /** The configured IRQ. */
660fd430a3a8cfa16505d04c7c577acf89d45a40vboxsync /** The configured I/O port base. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** Use UTC or local time initially. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** Disabled by HPET legacy mode. */
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync /* periodic timer */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /* second update */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** Pointer to the device instance - R3 Ptr. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** The periodic timer (rtcTimerPeriodic) - R3 Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** The second timer (rtcTimerSecond) - R3 Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** The second second timer (rtcTimerSecond2) - R3 Ptr. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** Pointer to the device instance - R0 Ptr. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** The periodic timer (rtcTimerPeriodic) - R0 Ptr. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** The second timer (rtcTimerSecond) - R0 Ptr. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /** The second second timer (rtcTimerSecond2) - R0 Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** Pointer to the device instance - RC Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** The periodic timer (rtcTimerPeriodic) - RC Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** The second timer (rtcTimerSecond) - RC Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** The second second timer (rtcTimerSecond2) - RC Ptr. */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /** The RTC registration structure. */
cce6b7c4e45848f22615d68ba5865b71abbfac95vboxsync /** The RTC device helpers. */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /** Number of release log entries. Used to prevent flooding. */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /** The current/previous timer period. Used to prevent flooding changes. */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /** HPET legacy mode notification interface. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncstatic void rtc_timer_update(RTCState *s, int64_t current_time)
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /* period in 32 kHz cycles */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /* compute 32 kHz clock */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync freq = TMTimerGetFreq(s->CTX_SUFF(pPeriodicTimer));
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync cur_clock = ASMMultU64ByU32DivByU32(current_time, 32768, freq);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync next_irq_clock = (cur_clock & ~(uint64_t)(period - 1)) + period;
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync s->next_periodic_time = ASMMultU64ByU32DivByU32(next_irq_clock, freq, 32768) + 1;
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync TMTimerSet(s->CTX_SUFF(pPeriodicTimer), s->next_periodic_time);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync LogRel(("RTC: period=%#x (%d) %u Hz\n", period, period, _32K / period));
e190faad3061288ae099cd3ea8a858bd224c00a7vboxsync if (TMTimerIsActive(s->CTX_SUFF(pPeriodicTimer)) && s->cRelLogEntries++ < 64)
839735dffe669517793471bfac0775fd19db414avboxsyncstatic void rtc_raise_irq(RTCState* pThis, uint32_t iLevel)
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync PDMDevHlpISASetIrq(pThis->CTX_SUFF(pDevIns), pThis->irq, iLevel);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncstatic void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync Log(("CMOS: Write idx %#04x: %#04x (old %#04x)\n", s->cmos_index, data, s->cmos_data[s->cmos_index]));
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /* if in set mode, do not update the time */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /* UIP bit is read only */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync rtc_timer_update(s, TMTimerGet(s->CTX_SUFF(pPeriodicTimer)));
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /* set mode: reset UIP mode */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync#if 0 /* This is probably wrong as it breaks changing the time/date in OS/2. */
65146b9eb3e96dbac286e55faa020bbfd74037d7vboxsync /* if disabling set mode, update the time */
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync rtc_timer_update(s, TMTimerGet(s->CTX_SUFF(pPeriodicTimer)));
7e10aea6606a51d35041e5a85f9e4f1bd19c4062vboxsync /* cannot write to them */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /* 24 hour format */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync /* 12 hour format */
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
0fcf82b2591711fa8980e8f5d9cad1b8f222d6d7vboxsync s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
d605d5391db09e6395a1c091f148f4b86af84bd3vboxsync/* month is between 0 and 11. */
int days_in_month;
rtc_copy_date(s);
int ret;
switch(s->cmos_index) {
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
case RTC_REG_A:
case RTC_REG_C:
rtc_raise_irq(s, 0);
return ret;
#ifdef IN_RING3
rtc_copy_date(s);
PDMBOTHCBDECL(int) rtcIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
PDMBOTHCBDECL(int) rtcIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
#ifdef IN_RING3
return VINF_SSM_DONT_CALL_AGAIN;
static DECLCALLBACK(int) rtcLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
int rc;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - u8Irq: saved=%#x config=%#x"), u8Irq, pThis->irq);
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - IOPortBase: saved=%RTiop config=%RTiop"), IOPortBase, pThis->IOPortBase);
bool fUTC;
return VINF_SUCCESS;
if ( period_code != 0
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
/* -=-=-=-=-=- based on bits from pc.c -=-=-=-=-=- */
return VINF_SUCCESS;
return NULL;
static DECLCALLBACK(void) rtcHpetLegacyNotify_ModeChanged(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated)
int rc;
bool fGCEnabled;
bool fR0Enabled;
return rc;
return rc;
return rc;
return rc;
return rc;
if (fGCEnabled)
return rc;
if (fR0Enabled)
return rc;
rc = PDMDevHlpSSMRegister3(pDevIns, RTC_SAVED_STATE_VERSION, sizeof(*pThis), rtcLiveExec, rtcSaveExec, rtcLoadExec);
return rc;
return rc;
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
sizeof(RTCState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,