Revision 7d932dfd
b/hw/hpet.c | ||
---|---|---|
30 | 30 |
#include "qemu-timer.h" |
31 | 31 |
#include "hpet_emul.h" |
32 | 32 |
#include "sysbus.h" |
33 |
#include "mc146818rtc.h" |
|
33 | 34 |
|
34 | 35 |
//#define HPET_DEBUG |
35 | 36 |
#ifdef HPET_DEBUG |
... | ... | |
58 | 59 |
SysBusDevice busdev; |
59 | 60 |
uint64_t hpet_offset; |
60 | 61 |
qemu_irq irqs[HPET_NUM_IRQ_ROUTES]; |
62 |
uint8_t rtc_irq_level; |
|
61 | 63 |
HPETTimer timer[HPET_NUM_TIMERS]; |
62 | 64 |
|
63 | 65 |
/* Memory-mapped, software visible registers */ |
... | ... | |
69 | 71 |
|
70 | 72 |
static HPETState *hpet_statep; |
71 | 73 |
|
72 |
uint32_t hpet_in_legacy_mode(void)
|
|
74 |
static uint32_t hpet_in_legacy_mode(HPETState *s)
|
|
73 | 75 |
{ |
74 |
if (!hpet_statep) { |
|
75 |
return 0; |
|
76 |
} |
|
77 |
return hpet_statep->config & HPET_CFG_LEGACY; |
|
76 |
return s->config & HPET_CFG_LEGACY; |
|
78 | 77 |
} |
79 | 78 |
|
80 | 79 |
static uint32_t timer_int_route(struct HPETTimer *timer) |
... | ... | |
166 | 165 |
{ |
167 | 166 |
int route; |
168 | 167 |
|
169 |
if (timer->tn <= 1 && hpet_in_legacy_mode()) { |
|
168 |
if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
|
|
170 | 169 |
/* if LegacyReplacementRoute bit is set, HPET specification requires |
171 | 170 |
* timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC, |
172 | 171 |
* timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. |
173 | 172 |
*/ |
174 |
route = (timer->tn == 0) ? 0 : 8;
|
|
173 |
route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
|
|
175 | 174 |
} else { |
176 | 175 |
route = timer_int_route(timer); |
177 | 176 |
} |
... | ... | |
515 | 514 |
/* i8254 and RTC are disabled when HPET is in legacy mode */ |
516 | 515 |
if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) { |
517 | 516 |
hpet_pit_disable(); |
517 |
qemu_irq_lower(s->irqs[RTC_ISA_IRQ]); |
|
518 | 518 |
} else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) { |
519 | 519 |
hpet_pit_enable(); |
520 |
qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level); |
|
520 | 521 |
} |
521 | 522 |
break; |
522 | 523 |
case HPET_CFG + 4: |
... | ... | |
607 | 608 |
count = 1; |
608 | 609 |
} |
609 | 610 |
|
611 |
static void hpet_handle_rtc_irq(void *opaque, int n, int level) |
|
612 |
{ |
|
613 |
HPETState *s = FROM_SYSBUS(HPETState, opaque); |
|
614 |
|
|
615 |
s->rtc_irq_level = level; |
|
616 |
if (!hpet_in_legacy_mode(s)) { |
|
617 |
qemu_set_irq(s->irqs[RTC_ISA_IRQ], level); |
|
618 |
} |
|
619 |
} |
|
620 |
|
|
610 | 621 |
static int hpet_init(SysBusDevice *dev) |
611 | 622 |
{ |
612 | 623 |
HPETState *s = FROM_SYSBUS(HPETState, dev); |
... | ... | |
625 | 636 |
timer->state = s; |
626 | 637 |
} |
627 | 638 |
|
639 |
isa_reserve_irq(RTC_ISA_IRQ); |
|
640 |
qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1); |
|
641 |
|
|
628 | 642 |
/* HPET Area */ |
629 | 643 |
iomemtype = cpu_register_io_memory(hpet_ram_read, |
630 | 644 |
hpet_ram_write, s); |
b/hw/hpet_emul.h | ||
---|---|---|
47 | 47 |
#define HPET_TN_INT_ROUTE_CAP_SHIFT 32 |
48 | 48 |
#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U |
49 | 49 |
|
50 |
#if defined TARGET_I386 |
|
51 |
extern uint32_t hpet_in_legacy_mode(void); |
|
52 |
#endif |
|
53 |
|
|
54 | 50 |
#endif |
b/hw/mc146818rtc.c | ||
---|---|---|
27 | 27 |
#include "pc.h" |
28 | 28 |
#include "apic.h" |
29 | 29 |
#include "isa.h" |
30 |
#include "hpet_emul.h" |
|
31 | 30 |
#include "mc146818rtc.h" |
32 | 31 |
|
33 | 32 |
//#define DEBUG_CMOS |
... | ... | |
101 | 100 |
QEMUTimer *second_timer2; |
102 | 101 |
} RTCState; |
103 | 102 |
|
104 |
static void rtc_irq_raise(qemu_irq irq) |
|
105 |
{ |
|
106 |
/* When HPET is operating in legacy mode, RTC interrupts are disabled |
|
107 |
* We block qemu_irq_raise, but not qemu_irq_lower, in case legacy |
|
108 |
* mode is established while interrupt is raised. We want it to |
|
109 |
* be lowered in any case |
|
110 |
*/ |
|
111 |
#if defined TARGET_I386 |
|
112 |
if (!hpet_in_legacy_mode()) |
|
113 |
#endif |
|
114 |
qemu_irq_raise(irq); |
|
115 |
} |
|
116 |
|
|
117 | 103 |
static void rtc_set_time(RTCState *s); |
118 | 104 |
static void rtc_copy_date(RTCState *s); |
119 | 105 |
|
... | ... | |
139 | 125 |
apic_reset_irq_delivered(); |
140 | 126 |
s->cmos_data[RTC_REG_C] |= 0xc0; |
141 | 127 |
DPRINTF_C("cmos: injecting from timer\n"); |
142 |
rtc_irq_raise(s->irq);
|
|
128 |
qemu_irq_raise(s->irq);
|
|
143 | 129 |
if (apic_get_irq_delivered()) { |
144 | 130 |
s->irq_coalesced--; |
145 | 131 |
DPRINTF_C("cmos: coalesced irqs decreased to %d\n", |
... | ... | |
155 | 141 |
{ |
156 | 142 |
int period_code, period; |
157 | 143 |
int64_t cur_clock, next_irq_clock; |
158 |
int enable_pie; |
|
159 | 144 |
|
160 | 145 |
period_code = s->cmos_data[RTC_REG_A] & 0x0f; |
161 |
#if defined TARGET_I386 |
|
162 |
/* disable periodic timer if hpet is in legacy mode, since interrupts are |
|
163 |
* disabled anyway. |
|
164 |
*/ |
|
165 |
enable_pie = !hpet_in_legacy_mode(); |
|
166 |
#else |
|
167 |
enable_pie = 1; |
|
168 |
#endif |
|
169 | 146 |
if (period_code != 0 |
170 |
&& (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
|
|
147 |
&& ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
|
|
171 | 148 |
|| ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) { |
172 | 149 |
if (period_code <= 2) |
173 | 150 |
period_code += 7; |
... | ... | |
206 | 183 |
if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) |
207 | 184 |
s->irq_reinject_on_ack_count = 0; |
208 | 185 |
apic_reset_irq_delivered(); |
209 |
rtc_irq_raise(s->irq);
|
|
186 |
qemu_irq_raise(s->irq);
|
|
210 | 187 |
if (!apic_get_irq_delivered()) { |
211 | 188 |
s->irq_coalesced++; |
212 | 189 |
rtc_coalesced_timer_update(s); |
... | ... | |
215 | 192 |
} |
216 | 193 |
} else |
217 | 194 |
#endif |
218 |
rtc_irq_raise(s->irq);
|
|
195 |
qemu_irq_raise(s->irq);
|
|
219 | 196 |
} |
220 | 197 |
if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) { |
221 | 198 |
/* Not square wave at all but we don't want 2048Hz interrupts! |
... | ... | |
444 | 421 |
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) { |
445 | 422 |
|
446 | 423 |
s->cmos_data[RTC_REG_C] |= 0xa0; |
447 |
rtc_irq_raise(s->irq);
|
|
424 |
qemu_irq_raise(s->irq);
|
|
448 | 425 |
} |
449 | 426 |
} |
450 | 427 |
|
451 | 428 |
/* update ended interrupt */ |
452 | 429 |
s->cmos_data[RTC_REG_C] |= REG_C_UF; |
453 | 430 |
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) { |
454 |
s->cmos_data[RTC_REG_C] |= REG_C_IRQF; |
|
455 |
rtc_irq_raise(s->irq);
|
|
431 |
s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
|
|
432 |
qemu_irq_raise(s->irq);
|
|
456 | 433 |
} |
457 | 434 |
|
458 | 435 |
/* clear update in progress bit */ |
... | ... | |
606 | 583 |
{ |
607 | 584 |
RTCState *s = DO_UPCAST(RTCState, dev, dev); |
608 | 585 |
int base = 0x70; |
609 |
int isairq = 8; |
|
610 |
|
|
611 |
isa_init_irq(dev, &s->irq, isairq); |
|
612 | 586 |
|
613 | 587 |
s->cmos_data[RTC_REG_A] = 0x26; |
614 | 588 |
s->cmos_data[RTC_REG_B] = 0x02; |
... | ... | |
638 | 612 |
return 0; |
639 | 613 |
} |
640 | 614 |
|
641 |
ISADevice *rtc_init(int base_year) |
|
615 |
ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
|
|
642 | 616 |
{ |
643 | 617 |
ISADevice *dev; |
618 |
RTCState *s; |
|
644 | 619 |
|
645 | 620 |
dev = isa_create("mc146818rtc"); |
621 |
s = DO_UPCAST(RTCState, dev, dev); |
|
646 | 622 |
qdev_prop_set_int32(&dev->qdev, "base_year", base_year); |
647 | 623 |
qdev_init_nofail(&dev->qdev); |
624 |
if (intercept_irq) { |
|
625 |
s->irq = intercept_irq; |
|
626 |
} else { |
|
627 |
isa_init_irq(dev, &s->irq, RTC_ISA_IRQ); |
|
628 |
} |
|
648 | 629 |
return dev; |
649 | 630 |
} |
650 | 631 |
|
b/hw/mc146818rtc.h | ||
---|---|---|
3 | 3 |
|
4 | 4 |
#include "isa.h" |
5 | 5 |
|
6 |
ISADevice *rtc_init(int base_year); |
|
6 |
#define RTC_ISA_IRQ 8 |
|
7 |
|
|
8 |
ISADevice *rtc_init(int base_year, qemu_irq intercept_irq); |
|
7 | 9 |
void rtc_set_memory(ISADevice *dev, int addr, int val); |
8 | 10 |
void rtc_set_date(ISADevice *dev, const struct tm *tm); |
9 | 11 |
|
b/hw/mips_jazz.c | ||
---|---|---|
259 | 259 |
fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds); |
260 | 260 |
|
261 | 261 |
/* Real time clock */ |
262 |
rtc_init(1980); |
|
262 |
rtc_init(1980, NULL);
|
|
263 | 263 |
s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL); |
264 | 264 |
cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc); |
265 | 265 |
|
b/hw/mips_malta.c | ||
---|---|---|
959 | 959 |
/* Super I/O */ |
960 | 960 |
isa_dev = isa_create_simple("i8042"); |
961 | 961 |
|
962 |
rtc_state = rtc_init(2000); |
|
962 |
rtc_state = rtc_init(2000, NULL);
|
|
963 | 963 |
serial_isa_init(0, serial_hds[0]); |
964 | 964 |
serial_isa_init(1, serial_hds[1]); |
965 | 965 |
if (parallel_hds[0]) |
b/hw/mips_r4k.c | ||
---|---|---|
267 | 267 |
isa_bus_new(NULL); |
268 | 268 |
isa_bus_irqs(i8259); |
269 | 269 |
|
270 |
rtc_state = rtc_init(2000); |
|
270 |
rtc_state = rtc_init(2000, NULL);
|
|
271 | 271 |
|
272 | 272 |
/* Register 64 KB of ISA IO space at 0x14000000 */ |
273 | 273 |
#ifdef TARGET_WORDS_BIGENDIAN |
b/hw/pc.c | ||
---|---|---|
943 | 943 |
int i; |
944 | 944 |
DriveInfo *fd[MAX_FD]; |
945 | 945 |
PITState *pit; |
946 |
qemu_irq rtc_irq = NULL; |
|
946 | 947 |
qemu_irq *a20_line; |
947 | 948 |
ISADevice *i8042; |
948 | 949 |
qemu_irq *cpu_exit_irq; |
... | ... | |
951 | 952 |
|
952 | 953 |
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); |
953 | 954 |
|
954 |
*rtc_state = rtc_init(2000); |
|
955 |
|
|
956 |
qemu_register_boot_set(pc_boot_set, *rtc_state); |
|
957 |
|
|
958 |
pit = pit_init(0x40, isa_reserve_irq(0)); |
|
959 |
pcspk_init(pit); |
|
960 | 955 |
if (!no_hpet) { |
961 | 956 |
DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL); |
962 | 957 |
|
963 | 958 |
for (i = 0; i < 24; i++) { |
964 | 959 |
sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]); |
965 | 960 |
} |
961 |
rtc_irq = qdev_get_gpio_in(hpet, 0); |
|
966 | 962 |
} |
963 |
*rtc_state = rtc_init(2000, rtc_irq); |
|
964 |
|
|
965 |
qemu_register_boot_set(pc_boot_set, *rtc_state); |
|
966 |
|
|
967 |
pit = pit_init(0x40, isa_reserve_irq(0)); |
|
968 |
pcspk_init(pit); |
|
967 | 969 |
|
968 | 970 |
for(i = 0; i < MAX_SERIAL_PORTS; i++) { |
969 | 971 |
if (serial_hds[i]) { |
b/hw/ppc_prep.c | ||
---|---|---|
696 | 696 |
pci_vga_init(pci_bus, 0, 0); |
697 | 697 |
// openpic = openpic_init(0x00000000, 0xF0000000, 1); |
698 | 698 |
// pit = pit_init(0x40, i8259[0]); |
699 |
rtc_init(2000); |
|
699 |
rtc_init(2000, NULL);
|
|
700 | 700 |
|
701 | 701 |
if (serial_hds[0]) |
702 | 702 |
serial_isa_init(0, serial_hds[0]); |
Also available in: Unified diff