#include "apic.h"
#include "isa.h"
#include "hpet_emul.h"
+#include "mc146818rtc.h"
//#define DEBUG_CMOS
+//#define DEBUG_COALESCED
+
+#ifdef DEBUG_CMOS
+# define CMOS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define CMOS_DPRINTF(format, ...) do { } while (0)
+#endif
+
+#ifdef DEBUG_COALESCED
+# define DPRINTF_C(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define DPRINTF_C(format, ...) do { } while (0)
+#endif
#define RTC_REINJECT_ON_ACK_COUNT 20
#define REG_C_PF 0x40
#define REG_C_AF 0x20
-struct RTCState {
+typedef struct RTCState {
ISADevice dev;
uint8_t cmos_data[128];
uint8_t cmos_index;
QEMUTimer *coalesced_timer;
QEMUTimer *second_timer;
QEMUTimer *second_timer2;
-};
+} RTCState;
static void rtc_irq_raise(qemu_irq irq)
{
if (s->irq_coalesced != 0) {
apic_reset_irq_delivered();
s->cmos_data[RTC_REG_C] |= 0xc0;
+ DPRINTF_C("cmos: injecting from timer\n");
rtc_irq_raise(s->irq);
if (apic_get_irq_delivered()) {
s->irq_coalesced--;
+ DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
+ s->irq_coalesced);
}
}
/* period in 32 Khz cycles */
period = 1 << (period_code - 1);
#ifdef TARGET_I386
- if(period != s->period)
+ if (period != s->period) {
s->irq_coalesced = (s->irq_coalesced * s->period) / period;
+ DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
+ }
s->period = period;
#endif
/* compute 32 khz clock */
if (!apic_get_irq_delivered()) {
s->irq_coalesced++;
rtc_coalesced_timer_update(s);
+ DPRINTF_C("cmos: coalesced irqs increased to %d\n",
+ s->irq_coalesced);
}
} else
#endif
if ((addr & 1) == 0) {
s->cmos_index = data & 0x7f;
} else {
-#ifdef DEBUG_CMOS
- printf("cmos: write index=0x%02x val=0x%02x\n",
- s->cmos_index, data);
-#endif
+ CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
+ s->cmos_index, data);
switch(s->cmos_index) {
case RTC_SECONDS_ALARM:
case RTC_MINUTES_ALARM:
s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
s->irq_reinject_on_ack_count++;
apic_reset_irq_delivered();
+ DPRINTF_C("cmos: injecting on ack\n");
qemu_irq_raise(s->irq);
- if (apic_get_irq_delivered())
+ if (apic_get_irq_delivered()) {
s->irq_coalesced--;
+ DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
+ s->irq_coalesced);
+ }
break;
}
#endif
ret = s->cmos_data[s->cmos_index];
break;
}
-#ifdef DEBUG_CMOS
- printf("cmos: read index=0x%02x val=0x%02x\n",
- s->cmos_index, ret);
-#endif
+ CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
+ s->cmos_index, ret);
return ret;
}
}
-void rtc_set_memory(RTCState *s, int addr, int val)
+void rtc_set_memory(ISADevice *dev, int addr, int val)
{
+ RTCState *s = DO_UPCAST(RTCState, dev, dev);
if (addr >= 0 && addr <= 127)
s->cmos_data[addr] = val;
}
-void rtc_set_date(RTCState *s, const struct tm *tm)
+void rtc_set_date(ISADevice *dev, const struct tm *tm)
{
+ RTCState *s = DO_UPCAST(RTCState, dev, dev);
s->current_tm = *tm;
rtc_copy_date(s);
}
#define REG_IBM_CENTURY_BYTE 0x32
#define REG_IBM_PS2_CENTURY_BYTE 0x37
-static void rtc_set_date_from_host(RTCState *s)
+static void rtc_set_date_from_host(ISADevice *dev)
{
+ RTCState *s = DO_UPCAST(RTCState, dev, dev);
struct tm tm;
int val;
/* set the CMOS date */
qemu_get_timedate(&tm, 0);
- rtc_set_date(s, &tm);
+ rtc_set_date(dev, &tm);
val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
- rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
- rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+ rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
+ rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val);
}
static int rtc_post_load(void *opaque, int version_id)
s->cmos_data[RTC_REG_C] = 0x00;
s->cmos_data[RTC_REG_D] = 0x80;
- rtc_set_date_from_host(s);
+ rtc_set_date_from_host(dev);
s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
#ifdef TARGET_I386
return 0;
}
-RTCState *rtc_init(int base_year)
+ISADevice *rtc_init(int base_year)
{
ISADevice *dev;
dev = isa_create("mc146818rtc");
qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
qdev_init_nofail(&dev->qdev);
- return DO_UPCAST(RTCState, dev, dev);
+ return dev;
}
static ISADeviceInfo mc146818rtc_info = {