Revision 100d9891 hw/mc146818rtc.c
b/hw/mc146818rtc.c | ||
---|---|---|
50 | 50 |
|
51 | 51 |
#define REG_A_UIP 0x80 |
52 | 52 |
|
53 |
#define REG_B_SET 0x80 |
|
54 |
#define REG_B_PIE 0x40 |
|
55 |
#define REG_B_AIE 0x20 |
|
56 |
#define REG_B_UIE 0x10 |
|
57 |
#define REG_B_DM 0x04 |
|
53 |
#define REG_B_SET 0x80 |
|
54 |
#define REG_B_PIE 0x40 |
|
55 |
#define REG_B_AIE 0x20 |
|
56 |
#define REG_B_UIE 0x10 |
|
57 |
#define REG_B_SQWE 0x08 |
|
58 |
#define REG_B_DM 0x04 |
|
58 | 59 |
|
59 | 60 |
struct RTCState { |
60 | 61 |
uint8_t cmos_data[128]; |
... | ... | |
62 | 63 |
struct tm current_tm; |
63 | 64 |
int base_year; |
64 | 65 |
qemu_irq irq; |
66 |
qemu_irq sqw_irq; |
|
65 | 67 |
int it_shift; |
66 | 68 |
/* periodic timer */ |
67 | 69 |
QEMUTimer *periodic_timer; |
... | ... | |
95 | 97 |
{ |
96 | 98 |
int period_code, period; |
97 | 99 |
int64_t cur_clock, next_irq_clock; |
100 |
int enable_pie; |
|
98 | 101 |
|
99 | 102 |
period_code = s->cmos_data[RTC_REG_A] & 0x0f; |
100 | 103 |
#if defined TARGET_I386 || defined TARGET_X86_64 |
101 | 104 |
/* disable periodic timer if hpet is in legacy mode, since interrupts are |
102 | 105 |
* disabled anyway. |
103 | 106 |
*/ |
104 |
if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
|
|
107 |
enable_pie = hpet_in_legacy_mode();
|
|
105 | 108 |
#else |
106 |
if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
|
|
109 |
enable_pie = 1;
|
|
107 | 110 |
#endif |
111 |
if (period_code != 0 |
|
112 |
&& (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie) |
|
113 |
|| ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) { |
|
108 | 114 |
if (period_code <= 2) |
109 | 115 |
period_code += 7; |
110 | 116 |
/* period in 32 Khz cycles */ |
... | ... | |
138 | 144 |
return; |
139 | 145 |
} |
140 | 146 |
#endif |
141 |
s->cmos_data[RTC_REG_C] |= 0xc0; |
|
142 |
rtc_irq_raise(s->irq); |
|
147 |
if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { |
|
148 |
s->cmos_data[RTC_REG_C] |= 0xc0; |
|
149 |
rtc_irq_raise(s->irq); |
|
150 |
} |
|
151 |
if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) { |
|
152 |
/* Not square wave at all but we don't want 2048Hz interrupts! |
|
153 |
Must be seen as a pulse. */ |
|
154 |
qemu_irq_raise(s->sqw_irq); |
|
155 |
} |
|
143 | 156 |
} |
144 | 157 |
|
145 | 158 |
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) |
... | ... | |
527 | 540 |
} |
528 | 541 |
#endif |
529 | 542 |
|
530 |
RTCState *rtc_init(int base, qemu_irq irq, int base_year)
|
|
543 |
RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year)
|
|
531 | 544 |
{ |
532 | 545 |
RTCState *s; |
533 | 546 |
|
534 | 547 |
s = qemu_mallocz(sizeof(RTCState)); |
535 | 548 |
|
536 | 549 |
s->irq = irq; |
550 |
s->sqw_irq = sqw_irq; |
|
537 | 551 |
s->cmos_data[RTC_REG_A] = 0x26; |
538 | 552 |
s->cmos_data[RTC_REG_B] = 0x02; |
539 | 553 |
s->cmos_data[RTC_REG_C] = 0x00; |
... | ... | |
563 | 577 |
return s; |
564 | 578 |
} |
565 | 579 |
|
580 |
RTCState *rtc_init(int base, qemu_irq irq, int base_year) |
|
581 |
{ |
|
582 |
return rtc_init_sqw(base, irq, NULL, base_year); |
|
583 |
} |
|
584 |
|
|
566 | 585 |
/* Memory mapped interface */ |
567 | 586 |
static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr) |
568 | 587 |
{ |
Also available in: Unified diff