@@ -114,6 +114,7 @@ typedef struct RTCState {
static void rtc_set_time(RTCState *s);
static void rtc_calibrate_time(RTCState *s);
static void rtc_set_cmos(RTCState *s);
+static inline int rtc_from_bcd(RTCState *s, int a);
static int32_t divider_reset;
@@ -267,15 +268,58 @@ static void rtc_update_timer(void *opaque)
}
}
+static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
+{
+ if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
+ hour %= 12;
+ if (s->cmos_data[RTC_HOURS] & 0x80) {
+ hour += 12;
+ }
+ }
+ return hour;
+}
+static uint32_t check_alarm(RTCState *s)
+{
+ uint8_t alarm_hour, alarm_min, alarm_sec;
+ uint8_t cur_hour, cur_min, cur_sec;
+
+ rtc_calibrate_time(s);
+ rtc_set_cmos(s);
+
+ alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
+ alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
+ alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
+ alarm_hour = convert_hour(s, alarm_hour);
+
+ cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
+ cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
+ cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
+ cur_hour = convert_hour(s, cur_hour);
+
+ if (((alarm_sec & 0xc0) == 0xc0 || alarm_sec == cur_sec) &&
+ ((alarm_min & 0xc0) == 0xc0 || alarm_min == cur_min) &&
+ ((alarm_hour & 0xc0) == 0xc0 || alarm_hour == cur_hour)) {
+ return 1;
+ }
+ return 0;
+
+}
+
static void rtc_update_timer2(void *opaque)
{
RTCState *s = opaque;
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
s->cmos_data[RTC_REG_C] |= REG_C_UF;
+ if (check_alarm(s)) {
+ s->cmos_data[RTC_REG_C] |= REG_C_AF;
+ }
+
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
- qemu_irq_raise(s->irq);
+ if (s->cmos_data[RTC_REG_B] & (REG_B_AIE | REG_B_UIE)) {
+ s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+ qemu_irq_raise(s->irq);
+ }
}
check_update_timer(s);
}
Add the alarm check when update cycle ended. If alarm is fired, also AIE bit is setting, then raise a interrupt Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> --- hw/mc146818rtc.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 46 insertions(+), 2 deletions(-) -- 1.7.1