qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [4268] Ignore the wrapping of acpi timer counter again.


From: Andrzej Zaborowski
Subject: [Qemu-devel] [4268] Ignore the wrapping of acpi timer counter again.
Date: Sun, 27 Apr 2008 22:57:10 +0000

Revision: 4268
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4268
Author:   balrog
Date:     2008-04-27 22:57:10 +0000 (Sun, 27 Apr 2008)

Log Message:
-----------
Ignore the wrapping of acpi timer counter again.

Revert problematic change to restore system_powerdown.

Modified Paths:
--------------
    trunk/hw/acpi.c

Modified: trunk/hw/acpi.c
===================================================================
--- trunk/hw/acpi.c     2008-04-27 21:45:18 UTC (rev 4267)
+++ trunk/hw/acpi.c     2008-04-27 22:57:10 UTC (rev 4268)
@@ -50,15 +50,12 @@
     uint8_t smb_data[32];
     uint8_t smb_index;
     qemu_irq irq;
-    int64_t pmtmr;
 } PIIX4PMState;
 
 #define RTC_EN (1 << 10)
 #define PWRBTN_EN (1 << 8)
 #define GBL_EN (1 << 5)
 #define TMROF_EN (1 << 0)
-#define TIMER_OVERFLOW_CNT (1 << 23)
-#define TIMER_MASK 0xffffffLL
 
 #define SCI_EN (1 << 0)
 
@@ -77,61 +74,47 @@
 
 PIIX4PMState *pm_state;
 
-static void update_pmtmr(PIIX4PMState *s)
-{
-    int64_t pmtmr;
-
-    pmtmr = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec)
-            & TIMER_MASK;
-
-    if (!(s->pmsts & TMROF_EN)) {
-        if ((pmtmr ^ s->pmtmr) & TIMER_OVERFLOW_CNT) {
-            s->pmsts |= TMROF_EN;
-            if (s->pmen & TMROF_EN)
-                qemu_set_irq(s->irq, 1);
-        } else {
-            /* Calculate when the timer will neet to set
-             * the overflow bit again */
-            uint64_t delta = TIMER_OVERFLOW_CNT -
-                    (pmtmr & (TIMER_OVERFLOW_CNT - 1));
-
-            delta = muldiv64(delta, ticks_per_sec, PM_FREQ);
-            qemu_mod_timer(s->tmr_timer, qemu_get_clock(vm_clock) + delta);
-        }
-    }
-
-    s->pmtmr = pmtmr;
-}
-
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
-    update_pmtmr(s);
-    return s->pmtmr & TIMER_MASK;
+    uint32_t d;
+    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
+    return d & 0xffffff;
 }
 
-
 static int get_pmsts(PIIX4PMState *s)
 {
-    /* Just increase the accurancy by double computing the timer value */
-    update_pmtmr(s);
-
-    return s->pmsts;
+    int64_t d;
+    int pmsts;
+    pmsts = s->pmsts;
+    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
+    if (d >= s->tmr_overflow_time)
+        s->pmsts |= TMROF_EN;
+    return pmsts;
 }
 
 static void pm_update_sci(PIIX4PMState *s)
 {
-    int sci_level;
+    int sci_level, pmsts;
+    int64_t expire_time;
 
-    sci_level = (((s->pmsts & s->pmen) & 
-                   (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
-    if (!sci_level)
-        qemu_set_irq(s->irq, sci_level);
+    pmsts = get_pmsts(s);
+    sci_level = (((pmsts & s->pmen) &
+                  (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
+    qemu_set_irq(s->irq, sci_level);
+    /* schedule a timer interruption if needed */
+    if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
+        expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
+        qemu_mod_timer(s->tmr_timer, expire_time);
+        s->tmr_overflow_time += 0x800000;
+    } else {
+        qemu_del_timer(s->tmr_timer);
+    }
 }
 
 static void pm_tmr_timer(void *opaque)
 {
     PIIX4PMState *s = opaque;
-    update_pmtmr(s);
+    pm_update_sci(s);
 }
 
 static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
@@ -140,9 +123,18 @@
     addr &= 0x3f;
     switch(addr) {
     case 0x00:
-        s->pmsts &= ~val;
-        update_pmtmr(s);
-        pm_update_sci(s);
+        {
+            int64_t d;
+            int pmsts;
+            pmsts = get_pmsts(s);
+            if (pmsts & val & TMROF_EN) {
+                /* if TMRSTS is reset, then compute the new overflow time */
+                d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
+                s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+            }
+            s->pmsts &= ~val;
+            pm_update_sci(s);
+        }
         break;
     case 0x02:
         s->pmen = val;






reply via email to

[Prev in Thread] Current Thread [Next in Thread]