Commit 7546c016e5e8fb58386f6b9b2f29d4b35fa935ce

Authored by balrog
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;