summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2008-06-12 00:54:48 -0400
committerGabe Black <gblack@eecs.umich.edu>2008-06-12 00:54:48 -0400
commit4f9a0402f629dbd78494bd7e820ffa41b0a5f245 (patch)
tree95083f875c9fe827509d47e4c484ec595f0fcf98
parent0368ccdedaa6b6fecb0f04924456953c92396188 (diff)
downloadgem5-4f9a0402f629dbd78494bd7e820ffa41b0a5f245.tar.xz
Dev: Seperate the 8254 timer from tsunami and use it in that and the PC.
-rw-r--r--src/dev/SConscript2
-rw-r--r--src/dev/alpha/tsunami_io.cc224
-rw-r--r--src/dev/alpha/tsunami_io.hh135
-rw-r--r--src/dev/intel_8254_timer.cc255
-rw-r--r--src/dev/intel_8254_timer.hh206
-rw-r--r--src/dev/pitreg.h75
-rw-r--r--src/dev/x86/south_bridge/i8254.cc30
-rw-r--r--src/dev/x86/south_bridge/i8254.hh16
-rw-r--r--src/dev/x86/south_bridge/south_bridge.cc4
9 files changed, 489 insertions, 458 deletions
diff --git a/src/dev/SConscript b/src/dev/SConscript
index ee7adb8c8..bd6b16c43 100644
--- a/src/dev/SConscript
+++ b/src/dev/SConscript
@@ -54,6 +54,7 @@ if env['FULL_SYSTEM']:
Source('i8254xGBe.cc')
Source('ide_ctrl.cc')
Source('ide_disk.cc')
+ Source('intel_8254_timer.cc')
Source('io_device.cc')
Source('isa_fake.cc')
Source('mc146818.cc')
@@ -84,6 +85,7 @@ if env['FULL_SYSTEM']:
TraceFlag('EthernetSM')
TraceFlag('IdeCtrl')
TraceFlag('IdeDisk')
+ TraceFlag('Intel8254Timer')
TraceFlag('IsaFake')
TraceFlag('MC146818')
TraceFlag('PCIDEV')
diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc
index 88999ecc5..3496aed14 100644
--- a/src/dev/alpha/tsunami_io.cc
+++ b/src/dev/alpha/tsunami_io.cc
@@ -62,230 +62,6 @@ TsunamiIO::TsunamiRTC::TsunamiRTC(const string &n, const TsunamiIOParams *p) :
{
}
-TsunamiIO::PITimer::PITimer(const string &name)
- : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"),
- counter2(name + ".counter2")
-{
- counter[0] = &counter0;
- counter[1] = &counter0;
- counter[2] = &counter0;
-}
-
-void
-TsunamiIO::PITimer::writeControl(const uint8_t data)
-{
- int rw;
- int sel;
-
- sel = GET_CTRL_SEL(data);
-
- if (sel == PIT_READ_BACK)
- panic("PITimer Read-Back Command is not implemented.\n");
-
- rw = GET_CTRL_RW(data);
-
- if (rw == PIT_RW_LATCH_COMMAND)
- counter[sel]->latchCount();
- else {
- counter[sel]->setRW(rw);
- counter[sel]->setMode(GET_CTRL_MODE(data));
- counter[sel]->setBCD(GET_CTRL_BCD(data));
- }
-}
-
-void
-TsunamiIO::PITimer::serialize(const string &base, ostream &os)
-{
- // serialize the counters
- counter0.serialize(base + ".counter0", os);
- counter1.serialize(base + ".counter1", os);
- counter2.serialize(base + ".counter2", os);
-}
-
-void
-TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- // unserialze the counters
- counter0.unserialize(base + ".counter0", cp, section);
- counter1.unserialize(base + ".counter1", cp, section);
- counter2.unserialize(base + ".counter2", cp, section);
-}
-
-TsunamiIO::PITimer::Counter::Counter(const string &name)
- : _name(name), event(this), count(0), latched_count(0), period(0),
- mode(0), output_high(false), latch_on(false), read_byte(LSB),
- write_byte(LSB)
-{
-
-}
-
-void
-TsunamiIO::PITimer::Counter::latchCount()
-{
- // behave like a real latch
- if(!latch_on) {
- latch_on = true;
- read_byte = LSB;
- latched_count = count;
- }
-}
-
-uint8_t
-TsunamiIO::PITimer::Counter::read()
-{
- if (latch_on) {
- switch (read_byte) {
- case LSB:
- read_byte = MSB;
- return (uint8_t)latched_count;
- break;
- case MSB:
- read_byte = LSB;
- latch_on = false;
- return latched_count >> 8;
- break;
- default:
- panic("Shouldn't be here");
- }
- } else {
- switch (read_byte) {
- case LSB:
- read_byte = MSB;
- return (uint8_t)count;
- break;
- case MSB:
- read_byte = LSB;
- return count >> 8;
- break;
- default:
- panic("Shouldn't be here");
- }
- }
-}
-
-void
-TsunamiIO::PITimer::Counter::write(const uint8_t data)
-{
- switch (write_byte) {
- case LSB:
- count = (count & 0xFF00) | data;
-
- if (event.scheduled())
- event.deschedule();
- output_high = false;
- write_byte = MSB;
- break;
-
- case MSB:
- count = (count & 0x00FF) | (data << 8);
- period = count;
-
- if (period > 0) {
- DPRINTF(Tsunami, "Timer set to curTick + %d\n",
- count * event.interval);
- event.schedule(curTick + count * event.interval);
- }
- write_byte = LSB;
- break;
- }
-}
-
-void
-TsunamiIO::PITimer::Counter::setRW(int rw_val)
-{
- if (rw_val != PIT_RW_16BIT)
- panic("Only LSB/MSB read/write is implemented.\n");
-}
-
-void
-TsunamiIO::PITimer::Counter::setMode(int mode_val)
-{
- if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN &&
- mode_val != PIT_MODE_SQWAVE)
- panic("PIT mode %#x is not implemented: \n", mode_val);
-
- mode = mode_val;
-}
-
-void
-TsunamiIO::PITimer::Counter::setBCD(int bcd_val)
-{
- if (bcd_val != PIT_BCD_FALSE)
- panic("PITimer does not implement BCD counts.\n");
-}
-
-bool
-TsunamiIO::PITimer::Counter::outputHigh()
-{
- return output_high;
-}
-
-void
-TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os)
-{
- paramOut(os, base + ".count", count);
- paramOut(os, base + ".latched_count", latched_count);
- paramOut(os, base + ".period", period);
- paramOut(os, base + ".mode", mode);
- paramOut(os, base + ".output_high", output_high);
- paramOut(os, base + ".latch_on", latch_on);
- paramOut(os, base + ".read_byte", read_byte);
- paramOut(os, base + ".write_byte", write_byte);
-
- Tick event_tick = 0;
- if (event.scheduled())
- event_tick = event.when();
- paramOut(os, base + ".event_tick", event_tick);
-}
-
-void
-TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- paramIn(cp, section, base + ".count", count);
- paramIn(cp, section, base + ".latched_count", latched_count);
- paramIn(cp, section, base + ".period", period);
- paramIn(cp, section, base + ".mode", mode);
- paramIn(cp, section, base + ".output_high", output_high);
- paramIn(cp, section, base + ".latch_on", latch_on);
- paramIn(cp, section, base + ".read_byte", read_byte);
- paramIn(cp, section, base + ".write_byte", write_byte);
-
- Tick event_tick;
- paramIn(cp, section, base + ".event_tick", event_tick);
- if (event_tick)
- event.schedule(event_tick);
-}
-
-TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
- : Event(&mainEventQueue)
-{
- interval = (Tick)(Clock::Float::s / 1193180.0);
- counter = c_ptr;
-}
-
-void
-TsunamiIO::PITimer::Counter::CounterEvent::process()
-{
- DPRINTF(Tsunami, "Timer Interrupt\n");
- switch (counter->mode) {
- case PIT_MODE_INTTC:
- counter->output_high = true;
- case PIT_MODE_RATEGEN:
- case PIT_MODE_SQWAVE:
- break;
- default:
- panic("Unimplemented PITimer mode.\n");
- }
-}
-
-const char *
-TsunamiIO::PITimer::Counter::CounterEvent::description() const
-{
- return "tsunami 8254 Interval timer";
-}
-
TsunamiIO::TsunamiIO(const Params *p)
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
rtc(p->name + ".rtc", p)
diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh
index 3972efa48..736f498c7 100644
--- a/src/dev/alpha/tsunami_io.hh
+++ b/src/dev/alpha/tsunami_io.hh
@@ -39,6 +39,7 @@
#include "base/range.hh"
#include "dev/alpha/tsunami.hh"
+#include "dev/intel_8254_timer.hh"
#include "dev/mc146818.hh"
#include "dev/io_device.hh"
#include "params/TsunamiIO.hh"
@@ -69,138 +70,6 @@ class TsunamiIO : public BasicPioDevice
}
};
- /** Programmable Interval Timer (Intel 8254) */
- class PITimer
- {
- /** Counter element for PIT */
- class Counter
- {
- /** Event for counter interrupt */
- class CounterEvent : public Event
- {
- private:
- /** Pointer back to Counter */
- Counter* counter;
- Tick interval;
-
- public:
- CounterEvent(Counter*);
-
- /** Event process */
- virtual void process();
-
- /** Event description */
- virtual const char *description() const;
-
- friend class Counter;
- };
-
- private:
- std::string _name;
- const std::string &name() const { return _name; }
-
- CounterEvent event;
-
- /** Current count value */
- uint16_t count;
-
- /** Latched count */
- uint16_t latched_count;
-
- /** Interrupt period */
- uint16_t period;
-
- /** Current mode of operation */
- uint8_t mode;
-
- /** Output goes high when the counter reaches zero */
- bool output_high;
-
- /** State of the count latch */
- bool latch_on;
-
- /** Set of values for read_byte and write_byte */
- enum {LSB, MSB};
-
- /** Determine which byte of a 16-bit count value to read/write */
- uint8_t read_byte, write_byte;
-
- public:
- Counter(const std::string &name);
-
- /** Latch the current count (if one is not already latched) */
- void latchCount();
-
- /** Set the read/write mode */
- void setRW(int rw_val);
-
- /** Set operational mode */
- void setMode(int mode_val);
-
- /** Set count encoding */
- void setBCD(int bcd_val);
-
- /** Read a count byte */
- uint8_t read();
-
- /** Write a count byte */
- void write(const uint8_t data);
-
- /** Is the output high? */
- bool outputHigh();
-
- /**
- * Serialize this object to the given output stream.
- * @param base The base name of the counter object.
- * @param os The stream to serialize to.
- */
- void serialize(const std::string &base, std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param base The base name of the counter object.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
- };
-
- private:
- std::string _name;
- const std::string &name() const { return _name; }
-
- /** PIT has three seperate counters */
- Counter *counter[3];
-
- public:
- /** Public way to access individual counters (avoid array accesses) */
- Counter counter0;
- Counter counter1;
- Counter counter2;
-
- PITimer(const std::string &name);
-
- /** Write control word */
- void writeControl(const uint8_t data);
-
- /**
- * Serialize this object to the given output stream.
- * @param base The base name of the counter object.
- * @param os The stream to serialize to.
- */
- void serialize(const std::string &base, std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param base The base name of the counter object.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
- };
-
/** Mask of the PIC1 */
uint8_t mask1;
@@ -223,7 +92,7 @@ class TsunamiIO : public BasicPioDevice
Tsunami *tsunami;
/** Intel 8253 Periodic Interval Timer */
- PITimer pitimer;
+ Intel8254Timer pitimer;
TsunamiRTC rtc;
diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc
new file mode 100644
index 000000000..16d09f582
--- /dev/null
+++ b/src/dev/intel_8254_timer.cc
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2004, 2005
+ * The Regents of The University of Michigan
+ * All Rights Reserved
+ *
+ * This code is part of the M5 simulator.
+ *
+ * Permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any
+ * purpose, so long as the copyright notice above, this grant of
+ * permission, and the disclaimer below appear in all copies made; and
+ * so long as the name of The University of Michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+ * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
+ * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGES.
+ *
+ * Authors: Ali G. Saidi
+ * Andrew L. Schultz
+ * Miguel J. Serrano
+ */
+
+#include "base/misc.hh"
+#include "dev/intel_8254_timer.hh"
+
+using namespace std;
+
+Intel8254Timer::Intel8254Timer(const string &name)
+ : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"),
+ counter2(name + ".counter2")
+{
+ counter[0] = &counter0;
+ counter[1] = &counter0;
+ counter[2] = &counter0;
+}
+
+void
+Intel8254Timer::writeControl(const CtrlReg data)
+{
+ int sel = data.sel;
+
+ if (sel == ReadBackCommand)
+ panic("PITimer Read-Back Command is not implemented.\n");
+
+ if (data.rw == LatchCommand)
+ counter[sel]->latchCount();
+ else {
+ counter[sel]->setRW(data.rw);
+ counter[sel]->setMode(data.mode);
+ counter[sel]->setBCD(data.bcd);
+ }
+}
+
+void
+Intel8254Timer::serialize(const string &base, ostream &os)
+{
+ // serialize the counters
+ counter0.serialize(base + ".counter0", os);
+ counter1.serialize(base + ".counter1", os);
+ counter2.serialize(base + ".counter2", os);
+}
+
+void
+Intel8254Timer::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ // unserialze the counters
+ counter0.unserialize(base + ".counter0", cp, section);
+ counter1.unserialize(base + ".counter1", cp, section);
+ counter2.unserialize(base + ".counter2", cp, section);
+}
+
+Intel8254Timer::Counter::Counter(const string &name)
+ : _name(name), event(this), count(0), latched_count(0), period(0),
+ mode(0), output_high(false), latch_on(false), read_byte(LSB),
+ write_byte(LSB)
+{
+
+}
+
+void
+Intel8254Timer::Counter::latchCount()
+{
+ // behave like a real latch
+ if(!latch_on) {
+ latch_on = true;
+ read_byte = LSB;
+ latched_count = count;
+ }
+}
+
+uint8_t
+Intel8254Timer::Counter::read()
+{
+ if (latch_on) {
+ switch (read_byte) {
+ case LSB:
+ read_byte = MSB;
+ return (uint8_t)latched_count;
+ break;
+ case MSB:
+ read_byte = LSB;
+ latch_on = false;
+ return latched_count >> 8;
+ break;
+ default:
+ panic("Shouldn't be here");
+ }
+ } else {
+ switch (read_byte) {
+ case LSB:
+ read_byte = MSB;
+ return (uint8_t)count;
+ break;
+ case MSB:
+ read_byte = LSB;
+ return count >> 8;
+ break;
+ default:
+ panic("Shouldn't be here");
+ }
+ }
+}
+
+void
+Intel8254Timer::Counter::write(const uint8_t data)
+{
+ switch (write_byte) {
+ case LSB:
+ count = (count & 0xFF00) | data;
+
+ if (event.scheduled())
+ event.deschedule();
+ output_high = false;
+ write_byte = MSB;
+ break;
+
+ case MSB:
+ count = (count & 0x00FF) | (data << 8);
+ period = count;
+
+ if (period > 0) {
+ DPRINTF(Intel8254Timer, "Timer set to curTick + %d\n",
+ count * event.interval);
+ event.schedule(curTick + count * event.interval);
+ }
+ write_byte = LSB;
+ break;
+ }
+}
+
+void
+Intel8254Timer::Counter::setRW(int rw_val)
+{
+ if (rw_val != TwoPhase)
+ panic("Only LSB/MSB read/write is implemented.\n");
+}
+
+void
+Intel8254Timer::Counter::setMode(int mode_val)
+{
+ if(mode_val != InitTc && mode_val != RateGen &&
+ mode_val != SquareWave)
+ panic("PIT mode %#x is not implemented: \n", mode_val);
+
+ mode = mode_val;
+}
+
+void
+Intel8254Timer::Counter::setBCD(int bcd_val)
+{
+ if (bcd_val)
+ panic("PITimer does not implement BCD counts.\n");
+}
+
+bool
+Intel8254Timer::Counter::outputHigh()
+{
+ return output_high;
+}
+
+void
+Intel8254Timer::Counter::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".count", count);
+ paramOut(os, base + ".latched_count", latched_count);
+ paramOut(os, base + ".period", period);
+ paramOut(os, base + ".mode", mode);
+ paramOut(os, base + ".output_high", output_high);
+ paramOut(os, base + ".latch_on", latch_on);
+ paramOut(os, base + ".read_byte", read_byte);
+ paramOut(os, base + ".write_byte", write_byte);
+
+ Tick event_tick = 0;
+ if (event.scheduled())
+ event_tick = event.when();
+ paramOut(os, base + ".event_tick", event_tick);
+}
+
+void
+Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".count", count);
+ paramIn(cp, section, base + ".latched_count", latched_count);
+ paramIn(cp, section, base + ".period", period);
+ paramIn(cp, section, base + ".mode", mode);
+ paramIn(cp, section, base + ".output_high", output_high);
+ paramIn(cp, section, base + ".latch_on", latch_on);
+ paramIn(cp, section, base + ".read_byte", read_byte);
+ paramIn(cp, section, base + ".write_byte", write_byte);
+
+ Tick event_tick;
+ paramIn(cp, section, base + ".event_tick", event_tick);
+ if (event_tick)
+ event.schedule(event_tick);
+}
+
+Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
+ : Event(&mainEventQueue)
+{
+ interval = (Tick)(Clock::Float::s / 1193180.0);
+ counter = c_ptr;
+}
+
+void
+Intel8254Timer::Counter::CounterEvent::process()
+{
+ DPRINTF(Intel8254Timer, "Timer Interrupt\n");
+ switch (counter->mode) {
+ case InitTc:
+ counter->output_high = true;
+ case RateGen:
+ case SquareWave:
+ break;
+ default:
+ panic("Unimplemented PITimer mode.\n");
+ }
+}
+
+const char *
+Intel8254Timer::Counter::CounterEvent::description() const
+{
+ return "tsunami 8254 Interval timer";
+}
diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh
new file mode 100644
index 000000000..c7c2b1591
--- /dev/null
+++ b/src/dev/intel_8254_timer.hh
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2004, 2005
+ * The Regents of The University of Michigan
+ * All Rights Reserved
+ *
+ * This code is part of the M5 simulator.
+ *
+ * Permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any
+ * purpose, so long as the copyright notice above, this grant of
+ * permission, and the disclaimer below appear in all copies made; and
+ * so long as the name of The University of Michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+ * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
+ * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGES.
+ *
+ * Authors: Ali G. Saidi
+ * Andrew L. Schultz
+ * Miguel J. Serrano
+ */
+
+#ifndef __DEV_8254_HH__
+#define __DEV_8254_HH__
+
+#include "base/bitunion.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+
+#include <string>
+#include <iostream>
+
+/** Programmable Interval Timer (Intel 8254) */
+class Intel8254Timer
+{
+ BitUnion8(CtrlReg)
+ Bitfield<7, 6> sel;
+ Bitfield<5, 4> rw;
+ Bitfield<3, 1> mode;
+ Bitfield<0> bcd;
+ EndBitUnion(CtrlReg)
+
+ enum SelectVal {
+ SelectCounter0,
+ SelectCounter1,
+ SelectCounter2,
+ ReadBackCommand
+ };
+
+ enum ReadWriteVal {
+ LatchCommand,
+ LsbOnly,
+ MsbOnly,
+ TwoPhase
+ };
+
+ enum ModeVal {
+ InitTc,
+ OneShot,
+ RateGen,
+ SquareWave,
+ SoftwareStrobe,
+ HardwareStrobe
+ };
+
+ /** Counter element for PIT */
+ class Counter
+ {
+ /** Event for counter interrupt */
+ class CounterEvent : public Event
+ {
+ private:
+ /** Pointer back to Counter */
+ Counter* counter;
+ Tick interval;
+
+ public:
+ CounterEvent(Counter*);
+
+ /** Event process */
+ virtual void process();
+
+ /** Event description */
+ virtual const char *description() const;
+
+ friend class Counter;
+ };
+
+ private:
+ std::string _name;
+ const std::string &name() const { return _name; }
+
+ CounterEvent event;
+
+ /** Current count value */
+ uint16_t count;
+
+ /** Latched count */
+ uint16_t latched_count;
+
+ /** Interrupt period */
+ uint16_t period;
+
+ /** Current mode of operation */
+ uint8_t mode;
+
+ /** Output goes high when the counter reaches zero */
+ bool output_high;
+
+ /** State of the count latch */
+ bool latch_on;
+
+ /** Set of values for read_byte and write_byte */
+ enum {LSB, MSB};
+
+ /** Determine which byte of a 16-bit count value to read/write */
+ uint8_t read_byte, write_byte;
+
+ public:
+ Counter(const std::string &name);
+
+ /** Latch the current count (if one is not already latched) */
+ void latchCount();
+
+ /** Set the read/write mode */
+ void setRW(int rw_val);
+
+ /** Set operational mode */
+ void setMode(int mode_val);
+
+ /** Set count encoding */
+ void setBCD(int bcd_val);
+
+ /** Read a count byte */
+ uint8_t read();
+
+ /** Write a count byte */
+ void write(const uint8_t data);
+
+ /** Is the output high? */
+ bool outputHigh();
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param base The base name of the counter object.
+ * @param os The stream to serialize to.
+ */
+ void serialize(const std::string &base, std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param base The base name of the counter object.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+ };
+
+ private:
+ std::string _name;
+ const std::string &name() const { return _name; }
+
+ /** PIT has three seperate counters */
+ Counter *counter[3];
+
+ public:
+ /** Public way to access individual counters (avoid array accesses) */
+ Counter counter0;
+ Counter counter1;
+ Counter counter2;
+
+ Intel8254Timer(const std::string &name);
+
+ /** Write control word */
+ void writeControl(const CtrlReg data);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param base The base name of the counter object.
+ * @param os The stream to serialize to.
+ */
+ void serialize(const std::string &base, std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param base The base name of the counter object.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+};
+
+#endif // __DEV_8254_HH__
diff --git a/src/dev/pitreg.h b/src/dev/pitreg.h
deleted file mode 100644
index d42925a41..000000000
--- a/src/dev/pitreg.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Miguel Serrano
- */
-
-/* @file
- * Device register definitions for a device's PCI config space
- */
-
-#ifndef __PITREG_H__
-#define __PITREG_H__
-
-#include <sys/types.h>
-
-// Control Word Format
-
-#define PIT_SEL_SHFT 0x6
-#define PIT_RW_SHFT 0x4
-#define PIT_MODE_SHFT 0x1
-#define PIT_BCD_SHFT 0x0
-
-#define PIT_SEL_MASK 0x3
-#define PIT_RW_MASK 0x3
-#define PIT_MODE_MASK 0x7
-#define PIT_BCD_MASK 0x1
-
-#define GET_CTRL_FIELD(x, s, m) (((x) >> s) & m)
-#define GET_CTRL_SEL(x) GET_CTRL_FIELD(x, PIT_SEL_SHFT, PIT_SEL_MASK)
-#define GET_CTRL_RW(x) GET_CTRL_FIELD(x, PIT_RW_SHFT, PIT_RW_MASK)
-#define GET_CTRL_MODE(x) GET_CTRL_FIELD(x, PIT_MODE_SHFT, PIT_MODE_MASK)
-#define GET_CTRL_BCD(x) GET_CTRL_FIELD(x, PIT_BCD_SHFT, PIT_BCD_MASK)
-
-#define PIT_READ_BACK 0x3
-
-#define PIT_RW_LATCH_COMMAND 0x0
-#define PIT_RW_LSB_ONLY 0x1
-#define PIT_RW_MSB_ONLY 0x2
-#define PIT_RW_16BIT 0x3
-
-#define PIT_MODE_INTTC 0x0
-#define PIT_MODE_ONESHOT 0x1
-#define PIT_MODE_RATEGEN 0x2
-#define PIT_MODE_SQWAVE 0x3
-#define PIT_MODE_SWSTROBE 0x4
-#define PIT_MODE_HWSTROBE 0x5
-
-#define PIT_BCD_FALSE 0x0
-#define PIT_BCD_TRUE 0x1
-
-#endif // __PITREG_H__
diff --git a/src/dev/x86/south_bridge/i8254.cc b/src/dev/x86/south_bridge/i8254.cc
index fb6723a51..7c3501c37 100644
--- a/src/dev/x86/south_bridge/i8254.cc
+++ b/src/dev/x86/south_bridge/i8254.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,21 +38,21 @@ X86ISA::I8254::read(PacketPtr pkt)
switch(pkt->getAddr() - addrRange.start)
{
case 0x0:
- warn("Reading from timer 0 counter.\n");
+ pkt->set(pit.counter0.read());
break;
case 0x1:
- warn("Reading from timer 1 counter.\n");
+ pkt->set(pit.counter1.read());
break;
case 0x2:
- warn("Reading from timer 2 counter.\n");
+ pkt->set(pit.counter2.read());
break;
case 0x3:
- fatal("Reading from timer control word which is read only.\n");
+ pkt->set(uint8_t(-1));
break;
default:
panic("Read from undefined i8254 register.\n");
}
- return SubDevice::read(pkt);
+ return latency;
}
Tick
@@ -62,25 +62,19 @@ X86ISA::I8254::write(PacketPtr pkt)
switch(pkt->getAddr() - addrRange.start)
{
case 0x0:
- warn("Writing to timer 0 counter.\n");
+ pit.counter0.write(pkt->get<uint8_t>());
break;
case 0x1:
- warn("Writing to timer 1 counter.\n");
+ pit.counter1.write(pkt->get<uint8_t>());
break;
case 0x2:
- warn("Writing to timer 2 counter.\n");
+ pit.counter2.write(pkt->get<uint8_t>());
break;
case 0x3:
- processControlWord(pkt->get<uint8_t>());
- return latency;
+ pit.writeControl(pkt->get<uint8_t>());
+ break;
default:
panic("Write to undefined i8254 register.\n");
}
- return SubDevice::write(pkt);
-}
-
-void
-X86ISA::I8254::processControlWord(uint8_t word)
-{
- warn("I8254 received control word %x.\n", word);
+ return latency;
}
diff --git a/src/dev/x86/south_bridge/i8254.hh b/src/dev/x86/south_bridge/i8254.hh
index f246fd8e4..519049e93 100644
--- a/src/dev/x86/south_bridge/i8254.hh
+++ b/src/dev/x86/south_bridge/i8254.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,24 +33,28 @@
#include "arch/x86/x86_traits.hh"
#include "base/range.hh"
+#include "dev/intel_8254_timer.hh"
#include "dev/x86/south_bridge/sub_device.hh"
+#include <string>
+
namespace X86ISA
{
class I8254 : public SubDevice
{
protected:
- void processControlWord(uint8_t word);
+ Intel8254Timer pit;
public:
- I8254()
+ I8254(const std::string &name) : pit(name)
{}
- I8254(Tick _latency) : SubDevice(_latency)
+ I8254(const std::string &name, Tick _latency) :
+ SubDevice(_latency), pit(name)
{}
- I8254(Addr start, Addr size, Tick _latency) :
- SubDevice(start, size, _latency)
+ I8254(const std::string &name, Addr start, Addr size, Tick _latency) :
+ SubDevice(start, size, _latency), pit(name)
{}
Tick read(PacketPtr pkt);
diff --git a/src/dev/x86/south_bridge/south_bridge.cc b/src/dev/x86/south_bridge/south_bridge.cc
index f25b3b811..cc20ea09e 100644
--- a/src/dev/x86/south_bridge/south_bridge.cc
+++ b/src/dev/x86/south_bridge/south_bridge.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -68,7 +68,7 @@ SouthBridge::write(PacketPtr pkt)
SouthBridge::SouthBridge(const Params *p) : PioDevice(p),
pic1(0x20, 2, p->pio_latency),
pic2(0xA0, 2, p->pio_latency),
- pit(0x40, 4, p->pio_latency),
+ pit(p->name + ".pit", 0x40, 4, p->pio_latency),
cmos(0x70, 2, p->pio_latency),
speaker(0x61, 1, p->pio_latency)
{