Basic X86 RTC code
This commit is contained in:
parent
1b82af5c11
commit
d9b68fc462
@ -31,6 +31,7 @@ src_amd64 = [
|
||||
"dev/x86/debugcons.c",
|
||||
"dev/x86/ide.c",
|
||||
"dev/x86/ps2.c",
|
||||
"dev/x86/rtc.c",
|
||||
"dev/x86/sercons.c",
|
||||
"dev/x86/vgacons.c",
|
||||
]
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "../dev/console.h"
|
||||
|
||||
extern void RTC_Init();
|
||||
extern void PS2_Init();
|
||||
extern void PCI_Init();
|
||||
extern void IDE_Init();
|
||||
@ -140,6 +141,8 @@ void Machine_Init()
|
||||
IOAPIC_Enable(0); // Enable timer interrupts
|
||||
Thread_Init();
|
||||
|
||||
RTC_Init();
|
||||
|
||||
PS2_Init();
|
||||
PCI_Init();
|
||||
IDE_Init();
|
||||
|
132
sys/dev/x86/rtc.c
Normal file
132
sys/dev/x86/rtc.c
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/kassert.h>
|
||||
#include <sys/kdebug.h>
|
||||
#include <sys/spinlock.h>
|
||||
|
||||
#include "ioport.h"
|
||||
|
||||
#define RTC_SECONDS 0x00
|
||||
#define RTC_MINUTES 0x02
|
||||
#define RTC_HOURS 0x04
|
||||
#define RTC_WEEKDAY 0x06
|
||||
#define RTC_DAY 0x07
|
||||
#define RTC_MONTH 0x08
|
||||
#define RTC_YEAR 0x09
|
||||
|
||||
uint64_t RTC_ReadTime();
|
||||
|
||||
void
|
||||
RTC_Init()
|
||||
{
|
||||
RTC_ReadTime();
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
RTC_ReadReg(uint8_t reg)
|
||||
{
|
||||
outb(0x70, reg);
|
||||
return inb(0x71);
|
||||
}
|
||||
|
||||
static bool
|
||||
RTC_IsLeapYear(uint64_t year)
|
||||
{
|
||||
if ((year % 4) != 0)
|
||||
return false;
|
||||
if ((year % 100) != 0)
|
||||
return true;
|
||||
if ((year % 400) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
RTC_DaysInMonth(uint64_t year, uint64_t month)
|
||||
{
|
||||
static const uint64_t days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
if ((month == 2) && RTC_IsLeapYear(year))
|
||||
return 29;
|
||||
else
|
||||
return days[month];
|
||||
}
|
||||
|
||||
static const char *dayOfWeek[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static const char *months[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
uint64_t
|
||||
RTC_ReadTime()
|
||||
{
|
||||
uint64_t days = 0;
|
||||
uint64_t secs = 0;
|
||||
uint64_t y, m;
|
||||
// Read RTC
|
||||
bool isPM = false;
|
||||
uint64_t seconds = RTC_ReadReg(RTC_SECONDS);
|
||||
uint64_t minutes = RTC_ReadReg(RTC_MINUTES);
|
||||
uint64_t hours = RTC_ReadReg(RTC_HOURS);
|
||||
uint64_t weekday = RTC_ReadReg(RTC_WEEKDAY);
|
||||
uint64_t day = RTC_ReadReg(RTC_DAY);
|
||||
uint64_t month = RTC_ReadReg(RTC_MONTH);
|
||||
uint64_t year = RTC_ReadReg(RTC_YEAR);
|
||||
uint8_t flags = RTC_ReadReg(0x0B);
|
||||
|
||||
// Convert BCD & 24-hour checks
|
||||
if (hours & 0x80) {
|
||||
isPM = true;
|
||||
}
|
||||
if ((flags & 0x04) == 0) {
|
||||
#define BCD_TO_BIN(_B) ((_B & 0x0F) + ((_B >> 4) * 10))
|
||||
seconds = BCD_TO_BIN(seconds);
|
||||
minutes = BCD_TO_BIN(minutes);
|
||||
hours = BCD_TO_BIN((hours & 0x7F));
|
||||
weekday = BCD_TO_BIN(weekday);
|
||||
day = BCD_TO_BIN(day);
|
||||
month = BCD_TO_BIN(month);
|
||||
year = BCD_TO_BIN(year);
|
||||
}
|
||||
if (((flags & 0x02) == 0) && isPM) {
|
||||
hours = (hours + 12) % 24;
|
||||
}
|
||||
|
||||
year += 2000;
|
||||
|
||||
kprintf("RTC: %s %s %d %02d:%02d:%02d %04d\n",
|
||||
dayOfWeek[weekday - 1], months[month - 1],
|
||||
day, hours, minutes, seconds, year);
|
||||
|
||||
// Convert to UNIX epoch
|
||||
for (y = 1970; y < year; y++) {
|
||||
if (RTC_IsLeapYear(y))
|
||||
days += 366;
|
||||
else
|
||||
days += 365;
|
||||
}
|
||||
|
||||
for (m = 0; m < month; m++) {
|
||||
days += RTC_DaysInMonth(year, month);
|
||||
}
|
||||
days += day;
|
||||
|
||||
secs = 24 * days + hours;
|
||||
secs = secs * 60 + minutes;
|
||||
secs = secs * 60 + seconds;
|
||||
|
||||
return secs;
|
||||
}
|
||||
|
||||
void
|
||||
Debug_Date()
|
||||
{
|
||||
RTC_ReadTime();
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(date, "Print date", Debug_Date);
|
||||
|
Loading…
Reference in New Issue
Block a user