X86: Keep track of what the initial count value was in the LAPIC timer.

This commit is contained in:
Gabe Black 2009-04-19 03:56:57 -07:00
parent 18b3863127
commit 8b2ac20753
2 changed files with 38 additions and 10 deletions

View file

@ -90,7 +90,7 @@ Intel8254Timer::unserialize(const string &base, Checkpoint *cp,
Intel8254Timer::Counter::Counter(Intel8254Timer *p, Intel8254Timer::Counter::Counter(Intel8254Timer *p,
const string &name, unsigned int _num) 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), latched_count(0), period(0), mode(0), output_high(false),
latch_on(false), read_byte(LSB), write_byte(LSB), parent(p) latch_on(false), read_byte(LSB), write_byte(LSB), parent(p)
{ {
@ -104,10 +104,24 @@ Intel8254Timer::Counter::latchCount()
if(!latch_on) { if(!latch_on) {
latch_on = true; latch_on = true;
read_byte = LSB; 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 uint8_t
Intel8254Timer::Counter::read() Intel8254Timer::Counter::read()
{ {
@ -126,6 +140,7 @@ Intel8254Timer::Counter::read()
panic("Shouldn't be here"); panic("Shouldn't be here");
} }
} else { } else {
uint16_t count = currentCount();
switch (read_byte) { switch (read_byte) {
case LSB: case LSB:
read_byte = MSB; read_byte = MSB;
@ -146,7 +161,7 @@ Intel8254Timer::Counter::write(const uint8_t data)
{ {
switch (write_byte) { switch (write_byte) {
case LSB: case LSB:
count = (count & 0xFF00) | data; initial_count = (initial_count & 0xFF00) | data;
if (event.scheduled()) if (event.scheduled())
parent->deschedule(event); parent->deschedule(event);
@ -155,13 +170,13 @@ Intel8254Timer::Counter::write(const uint8_t data)
break; break;
case MSB: 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 // In the RateGen or SquareWave modes, the timer wraps around and
// triggers on a value of 1, not 0. // triggers on a value of 1, not 0.
if (mode == RateGen || mode == SquareWave) if (mode == RateGen || mode == SquareWave)
period = count - 1; period = initial_count - 1;
else else
period = count; period = initial_count;
if (period > 0) if (period > 0)
event.setTo(period); event.setTo(period);
@ -204,7 +219,7 @@ Intel8254Timer::Counter::outputHigh()
void void
Intel8254Timer::Counter::serialize(const string &base, ostream &os) 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 + ".latched_count", latched_count);
paramOut(os, base + ".period", period); paramOut(os, base + ".period", period);
paramOut(os, base + ".mode", mode); paramOut(os, base + ".mode", mode);
@ -223,7 +238,7 @@ void
Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp, Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp,
const string &section) 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 + ".latched_count", latched_count);
paramIn(cp, section, base + ".period", period); paramIn(cp, section, base + ".period", period);
paramIn(cp, section, base + ".mode", mode); paramIn(cp, section, base + ".mode", mode);
@ -271,6 +286,14 @@ Intel8254Timer::Counter::CounterEvent::setTo(int clocks)
counter->parent->schedule(this, curTick + clocks * interval); counter->parent->schedule(this, curTick + clocks * interval);
} }
int
Intel8254Timer::Counter::CounterEvent::clocksLeft()
{
if (!scheduled())
return -1;
return (when() - curTick + interval - 1) / interval;
}
const char * const char *
Intel8254Timer::Counter::CounterEvent::description() const Intel8254Timer::Counter::CounterEvent::description() const
{ {

View file

@ -98,6 +98,8 @@ class Intel8254Timer : public EventManager
friend class Counter; friend class Counter;
void setTo(int clocks); void setTo(int clocks);
int clocksLeft();
}; };
private: private:
@ -108,8 +110,8 @@ class Intel8254Timer : public EventManager
CounterEvent event; CounterEvent event;
/** Current count value */ /** Initial count value */
uint16_t count; uint16_t initial_count;
/** Latched count */ /** Latched count */
uint16_t latched_count; uint16_t latched_count;
@ -141,6 +143,9 @@ class Intel8254Timer : public EventManager
/** Latch the current count (if one is not already latched) */ /** Latch the current count (if one is not already latched) */
void latchCount(); void latchCount();
/** Get the current count for this counter */
int currentCount();
/** Set the read/write mode */ /** Set the read/write mode */
void setRW(int rw_val); void setRW(int rw_val);