Timer: Fill out the periodic modes a little.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:56:07 +0000 (00:56 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:56:07 +0000 (00:56 -0400)
src/dev/intel_8254_timer.cc
src/dev/intel_8254_timer.hh

index 16d09f582e1637bd59716ac119c2c4b55f199bf6..802dd44f5254a235728ee3bea6404c09a2e15af3 100644 (file)
@@ -147,13 +147,16 @@ Intel8254Timer::Counter::write(const uint8_t data)
 
       case MSB:
         count = (count & 0x00FF) | (data << 8);
-        period = count;
+        // 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;
+        else
+            period = count;
+
+        if (period > 0)
+            event.setTo(period);
 
-        if (period > 0) {
-            DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n",
-                    count * event.interval);
-            event.schedule(curTick + count * event.interval);
-        }
         write_byte = LSB;
         break;
     }
@@ -240,14 +243,26 @@ Intel8254Timer::Counter::CounterEvent::process()
     switch (counter->mode) {
       case InitTc:
         counter->output_high = true;
+        break;
       case RateGen:
       case SquareWave:
+        setTo(counter->period);
         break;
       default:
         panic("Unimplemented PITimer mode.\n");
     }
 }
 
+void
+Intel8254Timer::Counter::CounterEvent::setTo(int clocks)
+{
+    if (clocks == 0)
+        panic("Timer can't be set to go off instantly.\n");
+    DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n",
+            clocks * interval);
+    schedule(curTick + clocks * interval);
+}
+
 const char *
 Intel8254Timer::Counter::CounterEvent::description() const
 {
index c7c2b1591b095280a90ac4eb39b06a3cbcf5bb73..23596a687c80b917d94a2361cc7584c93ff6fce2 100644 (file)
@@ -95,6 +95,8 @@ class Intel8254Timer
             virtual const char *description() const;
 
             friend class Counter;
+
+            void setTo(int clocks);
         };
 
       private: