Commit 7546c016e5e8fb58386f6b9b2f29d4b35fa935ce
1 parent
f3ae0704
Ignore the wrapping of acpi timer counter again.
Revert problematic change to restore system_powerdown. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4268 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
38 additions
and
46 deletions
hw/acpi.c
@@ -50,15 +50,12 @@ typedef struct PIIX4PMState { | @@ -50,15 +50,12 @@ typedef struct PIIX4PMState { | ||
50 | uint8_t smb_data[32]; | 50 | uint8_t smb_data[32]; |
51 | uint8_t smb_index; | 51 | uint8_t smb_index; |
52 | qemu_irq irq; | 52 | qemu_irq irq; |
53 | - int64_t pmtmr; | ||
54 | } PIIX4PMState; | 53 | } PIIX4PMState; |
55 | 54 | ||
56 | #define RTC_EN (1 << 10) | 55 | #define RTC_EN (1 << 10) |
57 | #define PWRBTN_EN (1 << 8) | 56 | #define PWRBTN_EN (1 << 8) |
58 | #define GBL_EN (1 << 5) | 57 | #define GBL_EN (1 << 5) |
59 | #define TMROF_EN (1 << 0) | 58 | #define TMROF_EN (1 << 0) |
60 | -#define TIMER_OVERFLOW_CNT (1 << 23) | ||
61 | -#define TIMER_MASK 0xffffffLL | ||
62 | 59 | ||
63 | #define SCI_EN (1 << 0) | 60 | #define SCI_EN (1 << 0) |
64 | 61 | ||
@@ -77,61 +74,47 @@ typedef struct PIIX4PMState { | @@ -77,61 +74,47 @@ typedef struct PIIX4PMState { | ||
77 | 74 | ||
78 | PIIX4PMState *pm_state; | 75 | PIIX4PMState *pm_state; |
79 | 76 | ||
80 | -static void update_pmtmr(PIIX4PMState *s) | ||
81 | -{ | ||
82 | - int64_t pmtmr; | ||
83 | - | ||
84 | - pmtmr = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec) | ||
85 | - & TIMER_MASK; | ||
86 | - | ||
87 | - if (!(s->pmsts & TMROF_EN)) { | ||
88 | - if ((pmtmr ^ s->pmtmr) & TIMER_OVERFLOW_CNT) { | ||
89 | - s->pmsts |= TMROF_EN; | ||
90 | - if (s->pmen & TMROF_EN) | ||
91 | - qemu_set_irq(s->irq, 1); | ||
92 | - } else { | ||
93 | - /* Calculate when the timer will neet to set | ||
94 | - * the overflow bit again */ | ||
95 | - uint64_t delta = TIMER_OVERFLOW_CNT - | ||
96 | - (pmtmr & (TIMER_OVERFLOW_CNT - 1)); | ||
97 | - | ||
98 | - delta = muldiv64(delta, ticks_per_sec, PM_FREQ); | ||
99 | - qemu_mod_timer(s->tmr_timer, qemu_get_clock(vm_clock) + delta); | ||
100 | - } | ||
101 | - } | ||
102 | - | ||
103 | - s->pmtmr = pmtmr; | ||
104 | -} | ||
105 | - | ||
106 | static uint32_t get_pmtmr(PIIX4PMState *s) | 77 | static uint32_t get_pmtmr(PIIX4PMState *s) |
107 | { | 78 | { |
108 | - update_pmtmr(s); | ||
109 | - return s->pmtmr & TIMER_MASK; | 79 | + uint32_t d; |
80 | + d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); | ||
81 | + return d & 0xffffff; | ||
110 | } | 82 | } |
111 | 83 | ||
112 | - | ||
113 | static int get_pmsts(PIIX4PMState *s) | 84 | static int get_pmsts(PIIX4PMState *s) |
114 | { | 85 | { |
115 | - /* Just increase the accurancy by double computing the timer value */ | ||
116 | - update_pmtmr(s); | ||
117 | - | ||
118 | - return s->pmsts; | 86 | + int64_t d; |
87 | + int pmsts; | ||
88 | + pmsts = s->pmsts; | ||
89 | + d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); | ||
90 | + if (d >= s->tmr_overflow_time) | ||
91 | + s->pmsts |= TMROF_EN; | ||
92 | + return pmsts; | ||
119 | } | 93 | } |
120 | 94 | ||
121 | static void pm_update_sci(PIIX4PMState *s) | 95 | static void pm_update_sci(PIIX4PMState *s) |
122 | { | 96 | { |
123 | - int sci_level; | ||
124 | - | ||
125 | - sci_level = (((s->pmsts & s->pmen) & | ||
126 | - (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); | ||
127 | - if (!sci_level) | ||
128 | - qemu_set_irq(s->irq, sci_level); | 97 | + int sci_level, pmsts; |
98 | + int64_t expire_time; | ||
99 | + | ||
100 | + pmsts = get_pmsts(s); | ||
101 | + sci_level = (((pmsts & s->pmen) & | ||
102 | + (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); | ||
103 | + qemu_set_irq(s->irq, sci_level); | ||
104 | + /* schedule a timer interruption if needed */ | ||
105 | + if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) { | ||
106 | + expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ); | ||
107 | + qemu_mod_timer(s->tmr_timer, expire_time); | ||
108 | + s->tmr_overflow_time += 0x800000; | ||
109 | + } else { | ||
110 | + qemu_del_timer(s->tmr_timer); | ||
111 | + } | ||
129 | } | 112 | } |
130 | 113 | ||
131 | static void pm_tmr_timer(void *opaque) | 114 | static void pm_tmr_timer(void *opaque) |
132 | { | 115 | { |
133 | PIIX4PMState *s = opaque; | 116 | PIIX4PMState *s = opaque; |
134 | - update_pmtmr(s); | 117 | + pm_update_sci(s); |
135 | } | 118 | } |
136 | 119 | ||
137 | static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) | 120 | static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) |
@@ -140,9 +123,18 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) | @@ -140,9 +123,18 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) | ||
140 | addr &= 0x3f; | 123 | addr &= 0x3f; |
141 | switch(addr) { | 124 | switch(addr) { |
142 | case 0x00: | 125 | case 0x00: |
143 | - s->pmsts &= ~val; | ||
144 | - update_pmtmr(s); | ||
145 | - pm_update_sci(s); | 126 | + { |
127 | + int64_t d; | ||
128 | + int pmsts; | ||
129 | + pmsts = get_pmsts(s); | ||
130 | + if (pmsts & val & TMROF_EN) { | ||
131 | + /* if TMRSTS is reset, then compute the new overflow time */ | ||
132 | + d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec); | ||
133 | + s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL; | ||
134 | + } | ||
135 | + s->pmsts &= ~val; | ||
136 | + pm_update_sci(s); | ||
137 | + } | ||
146 | break; | 138 | break; |
147 | case 0x02: | 139 | case 0x02: |
148 | s->pmen = val; | 140 | s->pmen = val; |