1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:07:47 +00:00

Kernel/x86: Move RTC and CMOS code to x86 arch-specific subdirectory

The RTC and CMOS are currently only supported for x86 platforms and use
specific x86 instructions to produce only certain x86 plaform operations
and results, therefore, we move them to the Arch/x86 specific directory.
This commit is contained in:
Liav A 2022-09-02 11:35:12 +03:00 committed by Linus Groh
parent e740d959df
commit d5ee03ef5b
12 changed files with 8 additions and 12 deletions

View file

@ -1,119 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Format.h>
#include <AK/Time.h>
#include <Kernel/Arch/Delay.h>
#include <Kernel/CMOS.h>
#include <Kernel/RTC.h>
namespace Kernel::RTC {
static time_t s_boot_time;
void initialize()
{
s_boot_time = now();
}
time_t boot_time()
{
return s_boot_time;
}
static bool update_in_progress()
{
return CMOS::read(0x0a) & 0x80;
}
static u8 bcd_to_binary(u8 bcd)
{
return (bcd & 0x0F) + ((bcd >> 4) * 10);
}
static bool try_to_read_registers(unsigned& year, unsigned& month, unsigned& day, unsigned& hour, unsigned& minute, unsigned& second)
{
// Note: Let's wait 0.01 seconds until we stop trying to query the RTC CMOS
size_t time_passed_in_milliseconds = 0;
bool update_in_progress_ended_successfully = false;
while (time_passed_in_milliseconds < 100) {
if (!update_in_progress()) {
update_in_progress_ended_successfully = true;
break;
}
microseconds_delay(1000);
time_passed_in_milliseconds++;
}
if (!update_in_progress_ended_successfully) {
year = 1970;
month = 1;
day = 1;
hour = 0;
minute = 0;
second = 0;
return false;
}
u8 status_b = CMOS::read(0x0b);
second = CMOS::read(0x00);
minute = CMOS::read(0x02);
hour = CMOS::read(0x04);
day = CMOS::read(0x07);
month = CMOS::read(0x08);
year = CMOS::read(0x09);
bool is_pm = hour & 0x80;
if (!(status_b & 0x04)) {
second = bcd_to_binary(second);
minute = bcd_to_binary(minute);
hour = bcd_to_binary(hour & 0x7F);
day = bcd_to_binary(day);
month = bcd_to_binary(month);
year = bcd_to_binary(year);
}
if (!(status_b & 0x02)) {
// In the 12 hour clock, midnight and noon are 12, not 0. Map it to 0.
hour %= 12;
if (is_pm)
hour += 12;
}
year += 2000;
return true;
}
time_t now()
{
auto check_registers_against_preloaded_values = [](unsigned year, unsigned month, unsigned day, unsigned hour, unsigned minute, unsigned second) {
unsigned checked_year, checked_month, checked_day, checked_hour, checked_minute, checked_second;
if (!try_to_read_registers(checked_year, checked_month, checked_day, checked_hour, checked_minute, checked_second))
return false;
return checked_year == year && checked_month == month && checked_day == day && checked_hour == hour && checked_minute == minute && checked_second == second;
};
unsigned year, month, day, hour, minute, second;
bool did_read_rtc_successfully = false;
for (size_t attempt = 0; attempt < 5; attempt++) {
if (!try_to_read_registers(year, month, day, hour, minute, second))
break;
if (check_registers_against_preloaded_values(year, month, day, hour, minute, second)) {
did_read_rtc_successfully = true;
break;
}
}
dmesgln("RTC: {} Year: {}, month: {}, day: {}, hour: {}, minute: {}, second: {}", (did_read_rtc_successfully ? "" : "(failed to read)"), year, month, day, hour, minute, second);
time_t days_since_epoch = years_to_days_since_epoch(year) + day_of_year(year, month, day);
return ((days_since_epoch * 24 + hour) * 60 + minute) * 60 + second;
}
}