X86: Make the real time clock actually keep track of time.
This commit is contained in:
parent
e8c0ca5cd1
commit
da3c3bfa98
2 changed files with 103 additions and 19 deletions
|
@ -43,28 +43,20 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
|
static uint8_t
|
||||||
bool bcd, Tick frequency)
|
bcdize(uint8_t val)
|
||||||
: EventManager(em), _name(n), event(this, frequency)
|
|
||||||
{
|
{
|
||||||
memset(clock_data, 0, sizeof(clock_data));
|
uint8_t result;
|
||||||
stat_regA = RTCA_32768HZ | RTCA_1024HZ;
|
result = val % 10;
|
||||||
stat_regB = RTCB_PRDC_IE | RTCB_24HR;
|
result += (val / 10) << 4;
|
||||||
if (!bcd)
|
return result;
|
||||||
stat_regB |= RTCB_BIN;
|
|
||||||
|
|
||||||
year = time.tm_year;
|
|
||||||
|
|
||||||
if (bcd) {
|
|
||||||
// The datasheet says that the year field can be either BCD or
|
|
||||||
// years since 1900. Linux seems to be happy with years since
|
|
||||||
// 1900.
|
|
||||||
year = year % 100;
|
|
||||||
int tens = year / 10;
|
|
||||||
int ones = year % 10;
|
|
||||||
year = (tens << 4) + ones;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MC146818::setTime(const struct tm time)
|
||||||
|
{
|
||||||
|
curTime = time;
|
||||||
|
year = time.tm_year;
|
||||||
// Unix is 0-11 for month, data seet says start at 1
|
// Unix is 0-11 for month, data seet says start at 1
|
||||||
mon = time.tm_mon + 1;
|
mon = time.tm_mon + 1;
|
||||||
mday = time.tm_mday;
|
mday = time.tm_mday;
|
||||||
|
@ -75,6 +67,30 @@ MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
|
||||||
// Datasheet says 1 is sunday
|
// Datasheet says 1 is sunday
|
||||||
wday = time.tm_wday + 1;
|
wday = time.tm_wday + 1;
|
||||||
|
|
||||||
|
if (!(stat_regB & RTCB_BIN)) {
|
||||||
|
// The datasheet says that the year field can be either BCD or
|
||||||
|
// years since 1900. Linux seems to be happy with years since
|
||||||
|
// 1900.
|
||||||
|
year = bcdize(year % 100);
|
||||||
|
mon = bcdize(mon);
|
||||||
|
mday = bcdize(mday);
|
||||||
|
hour = bcdize(hour);
|
||||||
|
min = bcdize(min);
|
||||||
|
sec = bcdize(sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
|
||||||
|
bool bcd, Tick frequency)
|
||||||
|
: EventManager(em), _name(n), event(this, frequency), tickEvent(this)
|
||||||
|
{
|
||||||
|
memset(clock_data, 0, sizeof(clock_data));
|
||||||
|
stat_regA = RTCA_32768HZ | RTCA_1024HZ;
|
||||||
|
stat_regB = RTCB_PRDC_IE | RTCB_24HR;
|
||||||
|
if (!bcd)
|
||||||
|
stat_regB |= RTCB_BIN;
|
||||||
|
|
||||||
|
setTime(time);
|
||||||
DPRINTFN("Real-time clock set to %s", asctime(&time));
|
DPRINTFN("Real-time clock set to %s", asctime(&time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +157,34 @@ MC146818::readData(uint8_t addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static time_t
|
||||||
|
mkutctime(struct tm *time)
|
||||||
|
{
|
||||||
|
time_t ret;
|
||||||
|
char *tz;
|
||||||
|
|
||||||
|
tz = getenv("TZ");
|
||||||
|
setenv("TZ", "", 1);
|
||||||
|
tzset();
|
||||||
|
ret = mktime(time);
|
||||||
|
if (tz)
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
else
|
||||||
|
unsetenv("TZ");
|
||||||
|
tzset();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MC146818::tickClock()
|
||||||
|
{
|
||||||
|
if (stat_regB & RTCB_NO_UPDT)
|
||||||
|
return;
|
||||||
|
time_t calTime = mkutctime(&curTime);
|
||||||
|
calTime++;
|
||||||
|
setTime(*gmtime(&calTime));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MC146818::serialize(const string &base, ostream &os)
|
MC146818::serialize(const string &base, ostream &os)
|
||||||
{
|
{
|
||||||
|
@ -190,3 +234,17 @@ MC146818::RTCEvent::description() const
|
||||||
{
|
{
|
||||||
return "RTC interrupt";
|
return "RTC interrupt";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MC146818::RTCTickEvent::process()
|
||||||
|
{
|
||||||
|
DPRINTF(MC146818, "RTC clock tick\n");
|
||||||
|
parent->schedule(this, curTick + Clock::Int::s);
|
||||||
|
parent->tickClock();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
MC146818::RTCTickEvent::description() const
|
||||||
|
{
|
||||||
|
return "RTC clock tick";
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,23 @@ class MC146818 : public EventManager
|
||||||
virtual const char *description() const;
|
virtual const char *description() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Event for RTC periodic interrupt */
|
||||||
|
struct RTCTickEvent : public Event
|
||||||
|
{
|
||||||
|
MC146818 * parent;
|
||||||
|
|
||||||
|
RTCTickEvent(MC146818 * _parent) : parent(_parent)
|
||||||
|
{
|
||||||
|
parent->schedule(this, curTick + Clock::Int::s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event process to occur at interrupt*/
|
||||||
|
void process();
|
||||||
|
|
||||||
|
/** Event description */
|
||||||
|
const char *description() const;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _name;
|
std::string _name;
|
||||||
const std::string &name() const { return _name; }
|
const std::string &name() const { return _name; }
|
||||||
|
@ -71,6 +88,9 @@ class MC146818 : public EventManager
|
||||||
/** RTC periodic interrupt event */
|
/** RTC periodic interrupt event */
|
||||||
RTCEvent event;
|
RTCEvent event;
|
||||||
|
|
||||||
|
/** RTC tick event */
|
||||||
|
RTCTickEvent tickEvent;
|
||||||
|
|
||||||
/** Data for real-time clock function */
|
/** Data for real-time clock function */
|
||||||
union {
|
union {
|
||||||
uint8_t clock_data[10];
|
uint8_t clock_data[10];
|
||||||
|
@ -89,6 +109,10 @@ class MC146818 : public EventManager
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tm curTime;
|
||||||
|
|
||||||
|
void setTime(const struct tm time);
|
||||||
|
|
||||||
/** RTC status register A */
|
/** RTC status register A */
|
||||||
uint8_t stat_regA;
|
uint8_t stat_regA;
|
||||||
|
|
||||||
|
@ -106,6 +130,8 @@ class MC146818 : public EventManager
|
||||||
/** RTC read data */
|
/** RTC read data */
|
||||||
uint8_t readData(const uint8_t addr);
|
uint8_t readData(const uint8_t addr);
|
||||||
|
|
||||||
|
void tickClock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize this object to the given output stream.
|
* Serialize this object to the given output stream.
|
||||||
* @param base The base name of the counter object.
|
* @param base The base name of the counter object.
|
||||||
|
|
Loading…
Reference in a new issue