X86: Keep track of what the initial count value was in the LAPIC timer.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 19 Apr 2009 10:56:57 +0000 (03:56 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 19 Apr 2009 10:56:57 +0000 (03:56 -0700)
src/dev/intel_8254_timer.cc
src/dev/intel_8254_timer.hh

index d5dd043e1d7d9168b39445612834efea489efed8..770df1c76dd547613c43d2e56240e4112d2f594a 100644 (file)
@@ -90,7 +90,7 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp,
 
 Intel8254Timer::Counter::Counter(Intel8254Timer *p,
         const string &name, unsigned int _num)
-    : _name(name), num(_num), event(this), count(0),
+    : _name(name), num(_num), event(this), initial_count(0),
       latched_count(0), period(0), mode(0), output_high(false),
       latch_on(false), read_byte(LSB), write_byte(LSB), parent(p)
 {
@@ -104,10 +104,24 @@ Intel8254Timer::Counter::latchCount()
     if(!latch_on) {
         latch_on = true;
         read_byte = LSB;
-        latched_count = count;
+        latched_count = currentCount();
     }
 }
 
+int
+Intel8254Timer::Counter::currentCount()
+{
+    int clocks = event.clocksLeft();
+    if (clocks == -1) {
+        warn_once("Reading current count from inactive timer.\n");
+        return 0;
+    }
+    if (mode == RateGen || mode == SquareWave)
+        return clocks + 1;
+    else
+        return clocks;
+}
+
 uint8_t
 Intel8254Timer::Counter::read()
 {
@@ -126,6 +140,7 @@ Intel8254Timer::Counter::read()
             panic("Shouldn't be here");
         }
     } else {
+        uint16_t count = currentCount();
         switch (read_byte) {
           case LSB:
             read_byte = MSB;
@@ -146,7 +161,7 @@ Intel8254Timer::Counter::write(const uint8_t data)
 {
     switch (write_byte) {
       case LSB:
-        count = (count & 0xFF00) | data;
+        initial_count = (initial_count & 0xFF00) | data;
 
         if (event.scheduled())
             parent->deschedule(event);
@@ -155,13 +170,13 @@ Intel8254Timer::Counter::write(const uint8_t data)
         break;
 
       case MSB:
-        count = (count & 0x00FF) | (data << 8);
+        initial_count = (initial_count & 0x00FF) | (data << 8);
         // In the RateGen or SquareWave modes, the timer wraps around and
         // triggers on a value of 1, not 0.
         if (mode == RateGen || mode == SquareWave)
-            period = count - 1;
+            period = initial_count - 1;
         else
-            period = count;
+            period = initial_count;
 
         if (period > 0)
             event.setTo(period);
@@ -204,7 +219,7 @@ Intel8254Timer::Counter::outputHigh()
 void
 Intel8254Timer::Counter::serialize(const string &base, ostream &os)
 {
-    paramOut(os, base + ".count", count);
+    paramOut(os, base + ".initial_count", initial_count);
     paramOut(os, base + ".latched_count", latched_count);
     paramOut(os, base + ".period", period);
     paramOut(os, base + ".mode", mode);
@@ -223,7 +238,7 @@ void
 Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
                                          const string &section)
 {
-    paramIn(cp, section, base + ".count", count);
+    paramIn(cp, section, base + ".initial_count", initial_count);
     paramIn(cp, section, base + ".latched_count", latched_count);
     paramIn(cp, section, base + ".period", period);
     paramIn(cp, section, base + ".mode", mode);
@@ -271,6 +286,14 @@ Intel8254Timer::Counter::CounterEvent::setTo(int clocks)
     counter->parent->schedule(this, curTick + clocks * interval);
 }
 
+int
+Intel8254Timer::Counter::CounterEvent::clocksLeft()
+{
+    if (!scheduled())
+        return -1;
+    return (when() - curTick + interval - 1) / interval;
+}
+
 const char *
 Intel8254Timer::Counter::CounterEvent::description() const
 {
index bb650d33bb2478872710ca72730249ce8db8bf12..1bc2ab87bbcc05aacae4c5b44f35eaa994af567b 100644 (file)
@@ -98,6 +98,8 @@ class Intel8254Timer : public EventManager
             friend class Counter;
 
             void setTo(int clocks);
+
+            int clocksLeft();
         };
 
       private:
@@ -108,8 +110,8 @@ class Intel8254Timer : public EventManager
 
         CounterEvent event;
 
-        /** Current count value */
-        uint16_t count;
+        /** Initial count value */
+        uint16_t initial_count;
 
         /** Latched count */
         uint16_t latched_count;
@@ -141,6 +143,9 @@ class Intel8254Timer : public EventManager
         /** Latch the current count (if one is not already latched) */
         void latchCount();
 
+        /** Get the current count for this counter */
+        int currentCount();
+
         /** Set the read/write mode */
         void setRW(int rw_val);