aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/hpet.c28
-rw-r--r--hw/hpet_emul.h4
-rw-r--r--hw/mc146818rtc.c49
-rw-r--r--hw/mc146818rtc.h4
-rw-r--r--hw/mips_jazz.c2
-rw-r--r--hw/mips_malta.c2
-rw-r--r--hw/mips_r4k.c2
-rw-r--r--hw/pc.c14
-rw-r--r--hw/ppc_prep.c2
9 files changed, 51 insertions, 56 deletions
diff --git a/hw/hpet.c b/hw/hpet.c
index 041dd84..edfe02e 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -30,6 +30,7 @@
#include "qemu-timer.h"
#include "hpet_emul.h"
#include "sysbus.h"
+#include "mc146818rtc.h"
//#define HPET_DEBUG
#ifdef HPET_DEBUG
@@ -58,6 +59,7 @@ typedef struct HPETState {
SysBusDevice busdev;
uint64_t hpet_offset;
qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+ uint8_t rtc_irq_level;
HPETTimer timer[HPET_NUM_TIMERS];
/* Memory-mapped, software visible registers */
@@ -69,12 +71,9 @@ typedef struct HPETState {
static HPETState *hpet_statep;
-uint32_t hpet_in_legacy_mode(void)
+static uint32_t hpet_in_legacy_mode(HPETState *s)
{
- if (!hpet_statep) {
- return 0;
- }
- return hpet_statep->config & HPET_CFG_LEGACY;
+ return s->config & HPET_CFG_LEGACY;
}
static uint32_t timer_int_route(struct HPETTimer *timer)
@@ -166,12 +165,12 @@ static void update_irq(struct HPETTimer *timer)
{
int route;
- if (timer->tn <= 1 && hpet_in_legacy_mode()) {
+ if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
/* if LegacyReplacementRoute bit is set, HPET specification requires
* timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
* timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
*/
- route = (timer->tn == 0) ? 0 : 8;
+ route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
} else {
route = timer_int_route(timer);
}
@@ -515,8 +514,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
/* i8254 and RTC are disabled when HPET is in legacy mode */
if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
hpet_pit_disable();
+ qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
} else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
hpet_pit_enable();
+ qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
}
break;
case HPET_CFG + 4:
@@ -607,6 +608,16 @@ static void hpet_reset(DeviceState *d)
count = 1;
}
+static void hpet_handle_rtc_irq(void *opaque, int n, int level)
+{
+ HPETState *s = FROM_SYSBUS(HPETState, opaque);
+
+ s->rtc_irq_level = level;
+ if (!hpet_in_legacy_mode(s)) {
+ qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
+ }
+}
+
static int hpet_init(SysBusDevice *dev)
{
HPETState *s = FROM_SYSBUS(HPETState, dev);
@@ -625,6 +636,9 @@ static int hpet_init(SysBusDevice *dev)
timer->state = s;
}
+ isa_reserve_irq(RTC_ISA_IRQ);
+ qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
+
/* HPET Area */
iomemtype = cpu_register_io_memory(hpet_ram_read,
hpet_ram_write, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 785f850..9c268cc 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -47,8 +47,4 @@
#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
-#if defined TARGET_I386
-extern uint32_t hpet_in_legacy_mode(void);
-#endif
-
#endif
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index c3e6a70..c3459bf 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -27,7 +27,6 @@
#include "pc.h"
#include "apic.h"
#include "isa.h"
-#include "hpet_emul.h"
#include "mc146818rtc.h"
//#define DEBUG_CMOS
@@ -101,19 +100,6 @@ typedef struct RTCState {
QEMUTimer *second_timer2;
} RTCState;
-static void rtc_irq_raise(qemu_irq irq)
-{
- /* When HPET is operating in legacy mode, RTC interrupts are disabled
- * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
- * mode is established while interrupt is raised. We want it to
- * be lowered in any case
- */
-#if defined TARGET_I386
- if (!hpet_in_legacy_mode())
-#endif
- qemu_irq_raise(irq);
-}
-
static void rtc_set_time(RTCState *s);
static void rtc_copy_date(RTCState *s);
@@ -139,7 +125,7 @@ static void rtc_coalesced_timer(void *opaque)
apic_reset_irq_delivered();
s->cmos_data[RTC_REG_C] |= 0xc0;
DPRINTF_C("cmos: injecting from timer\n");
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
if (apic_get_irq_delivered()) {
s->irq_coalesced--;
DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
@@ -155,19 +141,10 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
{
int period_code, period;
int64_t cur_clock, next_irq_clock;
- int enable_pie;
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
-#if defined TARGET_I386
- /* disable periodic timer if hpet is in legacy mode, since interrupts are
- * disabled anyway.
- */
- enable_pie = !hpet_in_legacy_mode();
-#else
- enable_pie = 1;
-#endif
if (period_code != 0
- && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
+ && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
|| ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
if (period_code <= 2)
period_code += 7;
@@ -206,7 +183,7 @@ static void rtc_periodic_timer(void *opaque)
if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
s->irq_reinject_on_ack_count = 0;
apic_reset_irq_delivered();
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
if (!apic_get_irq_delivered()) {
s->irq_coalesced++;
rtc_coalesced_timer_update(s);
@@ -215,7 +192,7 @@ static void rtc_periodic_timer(void *opaque)
}
} else
#endif
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
}
if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
/* Not square wave at all but we don't want 2048Hz interrupts!
@@ -444,15 +421,15 @@ static void rtc_update_second2(void *opaque)
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
s->cmos_data[RTC_REG_C] |= 0xa0;
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
}
}
/* update ended interrupt */
s->cmos_data[RTC_REG_C] |= REG_C_UF;
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
- rtc_irq_raise(s->irq);
+ s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+ qemu_irq_raise(s->irq);
}
/* clear update in progress bit */
@@ -606,9 +583,6 @@ static int rtc_initfn(ISADevice *dev)
{
RTCState *s = DO_UPCAST(RTCState, dev, dev);
int base = 0x70;
- int isairq = 8;
-
- isa_init_irq(dev, &s->irq, isairq);
s->cmos_data[RTC_REG_A] = 0x26;
s->cmos_data[RTC_REG_B] = 0x02;
@@ -638,13 +612,20 @@ static int rtc_initfn(ISADevice *dev)
return 0;
}
-ISADevice *rtc_init(int base_year)
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
{
ISADevice *dev;
+ RTCState *s;
dev = isa_create("mc146818rtc");
+ s = DO_UPCAST(RTCState, dev, dev);
qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
qdev_init_nofail(&dev->qdev);
+ if (intercept_irq) {
+ s->irq = intercept_irq;
+ } else {
+ isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
+ }
return dev;
}
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index 6f46a68..575968c 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -3,7 +3,9 @@
#include "isa.h"
-ISADevice *rtc_init(int base_year);
+#define RTC_ISA_IRQ 8
+
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq);
void rtc_set_memory(ISADevice *dev, int addr, int val);
void rtc_set_date(ISADevice *dev, const struct tm *tm);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index ead3a00..22db7a2 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -259,7 +259,7 @@ void mips_jazz_init (ram_addr_t ram_size,
fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
/* Real time clock */
- rtc_init(1980);
+ rtc_init(1980, NULL);
s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index a8f9d15..23de7f0 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -959,7 +959,7 @@ void mips_malta_init (ram_addr_t ram_size,
/* Super I/O */
isa_dev = isa_create_simple("i8042");
- rtc_state = rtc_init(2000);
+ rtc_state = rtc_init(2000, NULL);
serial_isa_init(0, serial_hds[0]);
serial_isa_init(1, serial_hds[1]);
if (parallel_hds[0])
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index f1fcfcd..5a96dea 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -267,7 +267,7 @@ void mips_r4k_init (ram_addr_t ram_size,
isa_bus_new(NULL);
isa_bus_irqs(i8259);
- rtc_state = rtc_init(2000);
+ rtc_state = rtc_init(2000, NULL);
/* Register 64 KB of ISA IO space at 0x14000000 */
#ifdef TARGET_WORDS_BIGENDIAN
diff --git a/hw/pc.c b/hw/pc.c
index ae31e2e..1491129 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -943,6 +943,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
int i;
DriveInfo *fd[MAX_FD];
PITState *pit;
+ qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042;
qemu_irq *cpu_exit_irq;
@@ -951,19 +952,20 @@ void pc_basic_device_init(qemu_irq *isa_irq,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- *rtc_state = rtc_init(2000);
-
- qemu_register_boot_set(pc_boot_set, *rtc_state);
-
- pit = pit_init(0x40, isa_reserve_irq(0));
- pcspk_init(pit);
if (!no_hpet) {
DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
for (i = 0; i < 24; i++) {
sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
}
+ rtc_irq = qdev_get_gpio_in(hpet, 0);
}
+ *rtc_state = rtc_init(2000, rtc_irq);
+
+ qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+ pit = pit_init(0x40, isa_reserve_irq(0));
+ pcspk_init(pit);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 16c9950..bb9e15f 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -696,7 +696,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
pci_vga_init(pci_bus, 0, 0);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
// pit = pit_init(0x40, i8259[0]);
- rtc_init(2000);
+ rtc_init(2000, NULL);
if (serial_hds[0])
serial_isa_init(0, serial_hds[0]);