From 72c6e9763ca61bc9d7de5f7080ee1c8a1c7c1562 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 21 Aug 2018 19:42:33 +0200 Subject: cleaning up a bit --- driver/timer.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 driver/timer.c (limited to 'driver/timer.c') diff --git a/driver/timer.c b/driver/timer.c new file mode 100644 index 0000000..2d4c7ff --- /dev/null +++ b/driver/timer.c @@ -0,0 +1,167 @@ +#define FOOLOS_MODULE_NAME "timer" +#include "timer.h" + +#include "asm/x86.h" + +static volatile uint64_t task_system_clock_start=0; + +// CMOS RTC + +// read real time clock register +static unsigned char get_rtc_reg(int reg) { + x86_outb(0x70, reg); //cmos at addr 0x70 + return x86_inb(0x71); //cmos data at addr 0x71 +} + +// check if cmos rtc update in progress +static int get_rtc_update_flag() { + x86_outb(0x70, 0x0A); + return (x86_inb(0x71) & 0x80); +} + +// get real time clock rom cmos (seconds since jan) +static uint64_t get_rtc_time() +{ + int CURRENT_YEAR = 2018; // Change this each year! + + int century_register = 0x00; // Set by ACPI table parsing code if possible + + unsigned char second; + unsigned char minute; + unsigned char hour; + unsigned char day; + unsigned char month; + unsigned int year; + + unsigned char century; + unsigned char last_second; + unsigned char last_minute; + unsigned char last_hour; + unsigned char last_day; + unsigned char last_month; + unsigned char last_year; + unsigned char last_century; + unsigned char registerB; + + // Note: This uses the "read registers until you get the same values twice in a row" technique + // to avoid getting dodgy/inconsistent values due to RTC updates + + while (get_rtc_update_flag()); // Make sure an update isn't in progress + second = get_rtc_reg(0x00); + minute = get_rtc_reg(0x02); + hour = get_rtc_reg(0x04); + day = get_rtc_reg(0x07); + month = get_rtc_reg(0x08); + year = get_rtc_reg(0x09); + + if(century_register != 0) { + century = get_rtc_reg(century_register); + } + + do { + last_second = second; + last_minute = minute; + last_hour = hour; + last_day = day; + last_month = month; + last_year = year; + last_century = century; + + while (get_rtc_update_flag()); // Make sure an update isn't in progress + second = get_rtc_reg(0x00); + minute = get_rtc_reg(0x02); + hour = get_rtc_reg(0x04); + day = get_rtc_reg(0x07); + month = get_rtc_reg(0x08); + year = get_rtc_reg(0x09); + if(century_register != 0) { + century = get_rtc_reg(century_register); + } + } while( (last_second != second) || (last_minute != minute) || (last_hour != hour) || + (last_day != day) || (last_month != month) || (last_year != year) || + (last_century != century) ); + + registerB = get_rtc_reg(0x0B); + + // Convert BCD to binary values if necessary + if (!(registerB & 0x04)) { + second = (second & 0x0F) + ((second / 16) * 10); + minute = (minute & 0x0F) + ((minute / 16) * 10); + hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80); + day = (day & 0x0F) + ((day / 16) * 10); + month = (month & 0x0F) + ((month / 16) * 10); + year = (year & 0x0F) + ((year / 16) * 10); + if(century_register != 0) { + century = (century & 0x0F) + ((century / 16) * 10); + } + } + + // Convert 12 hour clock to 24 hour clock if necessary + if (!(registerB & 0x02) && (hour & 0x80)) { + hour = ((hour & 0x7F) + 12) % 24; + } + + // Calculate the full (4-digit) year + if(century_register != 0) { + year += century * 100; + } else { + year += (CURRENT_YEAR / 100) * 100; + if(year < CURRENT_YEAR) year += 100; + } + + // thank you doug16k @ #osdev + // https://github.com/doug65536/dgos/blob/eab7080e69360493381669e7ce0ff27587d3127a/kernel/lib/time.cc + int days[] = { + 31, + (year-1900) % 4 ? 28 : + (year-1900) % 100 ? 29 : + (year-1900) % 400 ? 28 : + 29, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 + }; + + int yday = 0; + for (int m = 1; m < month; ++m) + yday += days[m-1]; + yday += day - 1; + + uint64_t epoch_seconds= ((uint64_t)(second)) + + minute * 60 + + hour * 3600 + + (yday) * 86400 + + (year-1900 - 70) * 365 * 86400 + + ((year-1900 - 69) / 4) * 86400 - + ((year-1900 - 1) / 100) * 86400 + + ((year-1900 + 299) / 400) * 86400; + + return epoch_seconds; +} + + +// PIT +uint64_t timer_init() +{ + uint64_t epoch_time=get_rtc_time(); + task_system_clock_start=epoch_time*25; // since pit ticks 25times a second + pit_init(); + return epoch_time; +} + +uint64_t timer_get_ms() +{ + return (pit_get_ticks()+task_system_clock_start)*40; +} + +uint64_t timer_get_uptime_ms() +{ + return pit_get_ticks()*40; +} -- cgit v1.2.3