dev: prevent intel 8254 timer counter events firing before startup
This change includes edits to Intel8254Timer to prevent counter events firing before startup to comply with SimObject initialization call sequence. Committed by: Nilay Vaish <nilay@cs.wisc.edu>
This commit is contained in:
parent
1c1fb2c988
commit
1693e526d0
|
@ -288,6 +288,7 @@ void
|
|||
TsunamiIO::startup()
|
||||
{
|
||||
rtc.startup();
|
||||
pitimer.startup();
|
||||
}
|
||||
|
||||
TsunamiIO *
|
||||
|
|
|
@ -89,13 +89,22 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp,
|
|||
counter[2]->unserialize(base + ".counter2", cp, section);
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::startup()
|
||||
{
|
||||
counter[0]->startup();
|
||||
counter[1]->startup();
|
||||
counter[2]->startup();
|
||||
}
|
||||
|
||||
Intel8254Timer::Counter::Counter(Intel8254Timer *p,
|
||||
const string &name, unsigned int _num)
|
||||
: _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)
|
||||
: _name(name), num(_num), event(this), running(false),
|
||||
initial_count(0), latched_count(0), period(0), mode(0),
|
||||
output_high(false), latch_on(false), read_byte(LSB),
|
||||
write_byte(LSB), parent(p)
|
||||
{
|
||||
|
||||
offset = period * event.getInterval();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -179,7 +188,9 @@ Intel8254Timer::Counter::write(const uint8_t data)
|
|||
else
|
||||
period = initial_count;
|
||||
|
||||
if (period > 0)
|
||||
offset = period * event.getInterval();
|
||||
|
||||
if (running && (period > 0))
|
||||
event.setTo(period);
|
||||
|
||||
write_byte = LSB;
|
||||
|
@ -229,10 +240,10 @@ Intel8254Timer::Counter::serialize(const string &base, ostream &os)
|
|||
paramOut(os, base + ".read_byte", read_byte);
|
||||
paramOut(os, base + ".write_byte", write_byte);
|
||||
|
||||
Tick event_tick = 0;
|
||||
Tick event_tick_offset = 0;
|
||||
if (event.scheduled())
|
||||
event_tick = event.when();
|
||||
paramOut(os, base + ".event_tick", event_tick);
|
||||
event_tick_offset = event.when() - curTick();
|
||||
paramOut(os, base + ".event_tick_offset", event_tick_offset);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -248,12 +259,20 @@ Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
|
|||
paramIn(cp, section, base + ".read_byte", read_byte);
|
||||
paramIn(cp, section, base + ".write_byte", write_byte);
|
||||
|
||||
Tick event_tick = 0;
|
||||
if (event.scheduled())
|
||||
parent->deschedule(event);
|
||||
paramIn(cp, section, base + ".event_tick", event_tick);
|
||||
if (event_tick)
|
||||
parent->schedule(event, event_tick);
|
||||
Tick event_tick_offset = 0;
|
||||
assert(!event.scheduled());
|
||||
paramIn(cp, section, base + ".event_tick_offset", event_tick_offset);
|
||||
offset = event_tick_offset;
|
||||
}
|
||||
|
||||
void
|
||||
Intel8254Timer::Counter::startup()
|
||||
{
|
||||
running = true;
|
||||
if ((period > 0) && (offset > 0))
|
||||
{
|
||||
parent->schedule(event, curTick() + offset);
|
||||
}
|
||||
}
|
||||
|
||||
Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
|
||||
|
@ -302,3 +321,10 @@ Intel8254Timer::Counter::CounterEvent::description() const
|
|||
{
|
||||
return "Intel 8254 Interval timer";
|
||||
}
|
||||
|
||||
Tick
|
||||
Intel8254Timer::Counter::CounterEvent::getInterval()
|
||||
{
|
||||
return interval;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ class Intel8254Timer : public EventManager
|
|||
void setTo(int clocks);
|
||||
|
||||
int clocksLeft();
|
||||
|
||||
Tick getInterval();
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -112,6 +114,9 @@ class Intel8254Timer : public EventManager
|
|||
|
||||
CounterEvent event;
|
||||
|
||||
/** True after startup is called. */
|
||||
bool running;
|
||||
|
||||
/** Initial count value */
|
||||
uint16_t initial_count;
|
||||
|
||||
|
@ -121,6 +126,9 @@ class Intel8254Timer : public EventManager
|
|||
/** Interrupt period */
|
||||
uint16_t period;
|
||||
|
||||
/** When to start ticking */
|
||||
Tick offset;
|
||||
|
||||
/** Current mode of operation */
|
||||
uint8_t mode;
|
||||
|
||||
|
@ -181,6 +189,9 @@ class Intel8254Timer : public EventManager
|
|||
*/
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
|
||||
/** Start ticking */
|
||||
void startup();
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -246,6 +257,9 @@ class Intel8254Timer : public EventManager
|
|||
*/
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
|
||||
/** Start ticking */
|
||||
void startup();
|
||||
};
|
||||
|
||||
#endif // __DEV_8254_HH__
|
||||
|
|
|
@ -146,6 +146,7 @@ void
|
|||
MaltaIO::startup()
|
||||
{
|
||||
rtc.startup();
|
||||
pitimer.startup();
|
||||
}
|
||||
|
||||
MaltaIO *
|
||||
|
|
|
@ -89,6 +89,12 @@ X86ISA::I8254::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
pit.unserialize("pit", cp, section);
|
||||
}
|
||||
|
||||
void
|
||||
X86ISA::I8254::startup()
|
||||
{
|
||||
pit.startup();
|
||||
}
|
||||
|
||||
X86ISA::I8254 *
|
||||
I8254Params::create()
|
||||
{
|
||||
|
|
|
@ -111,6 +111,7 @@ class I8254 : public BasicPioDevice
|
|||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
virtual void startup();
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue