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 50 uint8_t smb_data[32];
51 51 uint8_t smb_index;
52 52 qemu_irq irq;
53   - int64_t pmtmr;
54 53 } PIIX4PMState;
55 54  
56 55 #define RTC_EN (1 << 10)
57 56 #define PWRBTN_EN (1 << 8)
58 57 #define GBL_EN (1 << 5)
59 58 #define TMROF_EN (1 << 0)
60   -#define TIMER_OVERFLOW_CNT (1 << 23)
61   -#define TIMER_MASK 0xffffffLL
62 59  
63 60 #define SCI_EN (1 << 0)
64 61  
... ... @@ -77,61 +74,47 @@ typedef struct PIIX4PMState {
77 74  
78 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 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 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 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 114 static void pm_tmr_timer(void *opaque)
132 115 {
133 116 PIIX4PMState *s = opaque;
134   - update_pmtmr(s);
  117 + pm_update_sci(s);
135 118 }
136 119  
137 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 123 addr &= 0x3f;
141 124 switch(addr) {
142 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 138 break;
147 139 case 0x02:
148 140 s->pmen = val;
... ...