Dev: Seperate the 8254 timer from tsunami and use it in that and the PC.
This commit is contained in:
parent
0368ccdeda
commit
4f9a0402f6
9 changed files with 489 additions and 458 deletions
|
@ -54,6 +54,7 @@ if env['FULL_SYSTEM']:
|
||||||
Source('i8254xGBe.cc')
|
Source('i8254xGBe.cc')
|
||||||
Source('ide_ctrl.cc')
|
Source('ide_ctrl.cc')
|
||||||
Source('ide_disk.cc')
|
Source('ide_disk.cc')
|
||||||
|
Source('intel_8254_timer.cc')
|
||||||
Source('io_device.cc')
|
Source('io_device.cc')
|
||||||
Source('isa_fake.cc')
|
Source('isa_fake.cc')
|
||||||
Source('mc146818.cc')
|
Source('mc146818.cc')
|
||||||
|
@ -84,6 +85,7 @@ if env['FULL_SYSTEM']:
|
||||||
TraceFlag('EthernetSM')
|
TraceFlag('EthernetSM')
|
||||||
TraceFlag('IdeCtrl')
|
TraceFlag('IdeCtrl')
|
||||||
TraceFlag('IdeDisk')
|
TraceFlag('IdeDisk')
|
||||||
|
TraceFlag('Intel8254Timer')
|
||||||
TraceFlag('IsaFake')
|
TraceFlag('IsaFake')
|
||||||
TraceFlag('MC146818')
|
TraceFlag('MC146818')
|
||||||
TraceFlag('PCIDEV')
|
TraceFlag('PCIDEV')
|
||||||
|
|
|
@ -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 §ion)
|
|
||||||
{
|
|
||||||
// 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 §ion)
|
|
||||||
{
|
|
||||||
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)
|
TsunamiIO::TsunamiIO(const Params *p)
|
||||||
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
||||||
rtc(p->name + ".rtc", p)
|
rtc(p->name + ".rtc", p)
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include "base/range.hh"
|
#include "base/range.hh"
|
||||||
#include "dev/alpha/tsunami.hh"
|
#include "dev/alpha/tsunami.hh"
|
||||||
|
#include "dev/intel_8254_timer.hh"
|
||||||
#include "dev/mc146818.hh"
|
#include "dev/mc146818.hh"
|
||||||
#include "dev/io_device.hh"
|
#include "dev/io_device.hh"
|
||||||
#include "params/TsunamiIO.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 §ion);
|
|
||||||
};
|
|
||||||
|
|
||||||
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 §ion);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Mask of the PIC1 */
|
/** Mask of the PIC1 */
|
||||||
uint8_t mask1;
|
uint8_t mask1;
|
||||||
|
|
||||||
|
@ -223,7 +92,7 @@ class TsunamiIO : public BasicPioDevice
|
||||||
Tsunami *tsunami;
|
Tsunami *tsunami;
|
||||||
|
|
||||||
/** Intel 8253 Periodic Interval Timer */
|
/** Intel 8253 Periodic Interval Timer */
|
||||||
PITimer pitimer;
|
Intel8254Timer pitimer;
|
||||||
|
|
||||||
TsunamiRTC rtc;
|
TsunamiRTC rtc;
|
||||||
|
|
||||||
|
|
255
src/dev/intel_8254_timer.cc
Normal file
255
src/dev/intel_8254_timer.cc
Normal file
|
@ -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 §ion)
|
||||||
|
{
|
||||||
|
// 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 §ion)
|
||||||
|
{
|
||||||
|
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";
|
||||||
|
}
|
206
src/dev/intel_8254_timer.hh
Normal file
206
src/dev/intel_8254_timer.hh
Normal file
|
@ -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 §ion);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 §ion);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __DEV_8254_HH__
|
|
@ -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__
|
|
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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)
|
switch(pkt->getAddr() - addrRange.start)
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
warn("Reading from timer 0 counter.\n");
|
pkt->set(pit.counter0.read());
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
warn("Reading from timer 1 counter.\n");
|
pkt->set(pit.counter1.read());
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
warn("Reading from timer 2 counter.\n");
|
pkt->set(pit.counter2.read());
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
fatal("Reading from timer control word which is read only.\n");
|
pkt->set(uint8_t(-1));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Read from undefined i8254 register.\n");
|
panic("Read from undefined i8254 register.\n");
|
||||||
}
|
}
|
||||||
return SubDevice::read(pkt);
|
return latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tick
|
Tick
|
||||||
|
@ -62,25 +62,19 @@ X86ISA::I8254::write(PacketPtr pkt)
|
||||||
switch(pkt->getAddr() - addrRange.start)
|
switch(pkt->getAddr() - addrRange.start)
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
warn("Writing to timer 0 counter.\n");
|
pit.counter0.write(pkt->get<uint8_t>());
|
||||||
break;
|
break;
|
||||||
case 0x1:
|
case 0x1:
|
||||||
warn("Writing to timer 1 counter.\n");
|
pit.counter1.write(pkt->get<uint8_t>());
|
||||||
break;
|
break;
|
||||||
case 0x2:
|
case 0x2:
|
||||||
warn("Writing to timer 2 counter.\n");
|
pit.counter2.write(pkt->get<uint8_t>());
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
processControlWord(pkt->get<uint8_t>());
|
pit.writeControl(pkt->get<uint8_t>());
|
||||||
return latency;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Write to undefined i8254 register.\n");
|
panic("Write to undefined i8254 register.\n");
|
||||||
}
|
}
|
||||||
return SubDevice::write(pkt);
|
return latency;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
X86ISA::I8254::processControlWord(uint8_t word)
|
|
||||||
{
|
|
||||||
warn("I8254 received control word %x.\n", word);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -33,24 +33,28 @@
|
||||||
|
|
||||||
#include "arch/x86/x86_traits.hh"
|
#include "arch/x86/x86_traits.hh"
|
||||||
#include "base/range.hh"
|
#include "base/range.hh"
|
||||||
|
#include "dev/intel_8254_timer.hh"
|
||||||
#include "dev/x86/south_bridge/sub_device.hh"
|
#include "dev/x86/south_bridge/sub_device.hh"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
|
|
||||||
class I8254 : public SubDevice
|
class I8254 : public SubDevice
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void processControlWord(uint8_t word);
|
Intel8254Timer pit;
|
||||||
|
|
||||||
public:
|
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) :
|
I8254(const std::string &name, Addr start, Addr size, Tick _latency) :
|
||||||
SubDevice(start, size, _latency)
|
SubDevice(start, size, _latency), pit(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Tick read(PacketPtr pkt);
|
Tick read(PacketPtr pkt);
|
||||||
|
|
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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),
|
SouthBridge::SouthBridge(const Params *p) : PioDevice(p),
|
||||||
pic1(0x20, 2, p->pio_latency),
|
pic1(0x20, 2, p->pio_latency),
|
||||||
pic2(0xA0, 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),
|
cmos(0x70, 2, p->pio_latency),
|
||||||
speaker(0x61, 1, p->pio_latency)
|
speaker(0x61, 1, p->pio_latency)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue