x86: re-enable RTC
This commit is contained in:
parent
56fbcefa80
commit
8db9c08224
@ -2,23 +2,44 @@ use core::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use yggdrasil_abi::time::SystemTime;
|
||||
|
||||
static MONOTONIC_MILLIS: AtomicU64 = AtomicU64::new(0);
|
||||
// Millisecond resolution
|
||||
const NANOSECONDS_IN_SECOND: u64 = 1_000_000_000;
|
||||
const TIME_RESOLUTION_NS: u64 = 1_000_000;
|
||||
pub const TICKS_PER_SEC: u64 = NANOSECONDS_IN_SECOND / TIME_RESOLUTION_NS;
|
||||
|
||||
pub fn monotonic_time() -> SystemTime {
|
||||
let millis = MONOTONIC_MILLIS.load(Ordering::Acquire);
|
||||
let nanoseconds = (millis % 1000) * 1000000;
|
||||
let seconds = millis / 1000;
|
||||
static MONOTONIC_TIME: AtomicU64 = AtomicU64::new(0);
|
||||
static REAL_TIME_OFFSET: AtomicU64 = AtomicU64::new(0);
|
||||
static REAL_TIME: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
#[inline]
|
||||
fn make_time(ticks: u64) -> SystemTime {
|
||||
SystemTime {
|
||||
seconds,
|
||||
nanoseconds,
|
||||
seconds: ticks / TICKS_PER_SEC,
|
||||
nanoseconds: (ticks % TICKS_PER_SEC) * TIME_RESOLUTION_NS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_ticks(ticks: u64) -> u64 {
|
||||
MONOTONIC_MILLIS.fetch_add(ticks, Ordering::Release)
|
||||
pub fn real_time() -> SystemTime {
|
||||
make_time(REAL_TIME.load(Ordering::Acquire) + REAL_TIME_OFFSET.load(Ordering::Relaxed))
|
||||
}
|
||||
|
||||
pub fn set_ticks(ticks: u64) -> u64 {
|
||||
MONOTONIC_MILLIS.swap(ticks, Ordering::Release)
|
||||
pub fn monotonic_time() -> SystemTime {
|
||||
make_time(MONOTONIC_TIME.load(Ordering::Acquire))
|
||||
}
|
||||
|
||||
pub fn add_ticks(ticks: u64) {
|
||||
MONOTONIC_TIME.fetch_add(ticks, Ordering::Release);
|
||||
REAL_TIME_OFFSET.fetch_add(ticks, Ordering::Release);
|
||||
}
|
||||
|
||||
pub fn set_real_time(ticks: u64, reset: bool) {
|
||||
REAL_TIME.store(ticks, Ordering::Release);
|
||||
if reset {
|
||||
REAL_TIME_OFFSET.store(0, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_ticks(ticks: u64) {
|
||||
MONOTONIC_TIME.store(ticks, Ordering::Release);
|
||||
REAL_TIME_OFFSET.store(ticks, Ordering::Release);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ mod peripherals;
|
||||
use crate::{
|
||||
arch::x86::{
|
||||
intrinsics::IoPortAccess,
|
||||
peripherals::{i8253::I8253, ps2::PS2Controller},
|
||||
peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc},
|
||||
ISA_IRQ_OFFSET,
|
||||
},
|
||||
fs::{Initrd, INITRD_DATA},
|
||||
@ -241,6 +241,9 @@ impl I686 {
|
||||
if let Err(error) = PS2Controller::setup() {
|
||||
log::error!("Could not initialize PS/2 Controller: {error:?}");
|
||||
}
|
||||
if let Err(error) = Rtc::setup() {
|
||||
log::error!("RTC init error: {error:?}");
|
||||
}
|
||||
|
||||
// Setup text framebuffer
|
||||
// TODO check if video mode is set from boot info
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod i8253;
|
||||
pub mod i8259;
|
||||
pub mod ps2;
|
||||
// pub mod rtc;
|
||||
pub mod rtc;
|
||||
pub mod serial;
|
||||
|
@ -1,19 +1,16 @@
|
||||
use abi::{error::Error, time::SystemTime};
|
||||
use abi::error::Error;
|
||||
use alloc::sync::Arc;
|
||||
use device_api::{
|
||||
device::Device,
|
||||
interrupt::{InterruptHandler, Irq},
|
||||
timer::RealTimeProviderDevice,
|
||||
Device,
|
||||
};
|
||||
use kernel_arch::{Architecture, ArchitectureImpl};
|
||||
use libk_device::{external_interrupt_controller, register_real_time_provider};
|
||||
use libk::{device::external_interrupt_controller, time};
|
||||
use libk_util::sync::IrqSafeSpinlock;
|
||||
|
||||
use crate::{
|
||||
arch::x86::{
|
||||
use crate::arch::x86::{
|
||||
intrinsics::{io_wait, IoPort, IoPortAccess},
|
||||
ISA_IRQ_OFFSET,
|
||||
},
|
||||
device::timer::GLOBAL_TIME,
|
||||
};
|
||||
|
||||
const NMI_DISABLE: u8 = 1 << 7;
|
||||
@ -130,13 +127,13 @@ impl Inner {
|
||||
}
|
||||
|
||||
impl InterruptHandler for Rtc {
|
||||
fn handle_irq(&'static self, _vector: Option<usize>) -> bool {
|
||||
fn handle_irq(self: Arc<Self>, _vector: Option<usize>) -> bool {
|
||||
let mut inner = self.inner.lock();
|
||||
if inner.counter == 0 {
|
||||
let time = inner.read_date_time();
|
||||
inner.last_timestamp = Some(time);
|
||||
|
||||
GLOBAL_TIME.update_from_rtc(time.into(), false);
|
||||
time::set_real_time(time.to_ticks(), true);
|
||||
}
|
||||
inner.read_reg(CMOS_REG_STATUS_C);
|
||||
|
||||
@ -146,38 +143,27 @@ impl InterruptHandler for Rtc {
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
"x86 RTC IRQ"
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for Rtc {
|
||||
unsafe fn init(&'static self) -> Result<(), Error> {
|
||||
register_real_time_provider(self);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
||||
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
|
||||
let irq = Irq::External(ISA_IRQ_OFFSET + 8);
|
||||
let intc = external_interrupt_controller();
|
||||
let intc = external_interrupt_controller()?;
|
||||
self.inner.lock().setup_irq();
|
||||
intc.register_irq(irq, Default::default(), self)?;
|
||||
intc.register_irq(irq, Default::default(), self.clone())?;
|
||||
intc.enable_irq(irq)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_name(&self) -> &'static str {
|
||||
fn display_name(&self) -> &str {
|
||||
"x86 RTC"
|
||||
}
|
||||
}
|
||||
|
||||
impl RealTimeProviderDevice for Rtc {
|
||||
fn real_timestamp(&self) -> Result<SystemTime, Error> {
|
||||
self.inner
|
||||
.lock()
|
||||
.last_timestamp
|
||||
.map(Into::into)
|
||||
.ok_or(Error::InvalidOperation)
|
||||
}
|
||||
}
|
||||
|
||||
impl Rtc {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
@ -189,30 +175,32 @@ impl Rtc {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup() -> Result<Arc<Self>, Error> {
|
||||
let this = Arc::new(Self::new());
|
||||
unsafe { this.clone().init_irq() }?;
|
||||
Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateTime> for SystemTime {
|
||||
fn from(value: DateTime) -> Self {
|
||||
impl DateTime {
|
||||
pub fn to_ticks(self) -> u64 {
|
||||
let date = chrono::NaiveDate::from_ymd_opt(
|
||||
2000 + value.year as i32,
|
||||
value.month as u32,
|
||||
value.day_of_month as u32,
|
||||
2000 + self.year as i32,
|
||||
self.month as u32,
|
||||
self.day_of_month as u32,
|
||||
)
|
||||
.unwrap();
|
||||
let time = chrono::NaiveTime::from_hms_opt(
|
||||
value.hours as u32,
|
||||
value.minutes as u32,
|
||||
value.seconds as u32,
|
||||
self.hours as u32,
|
||||
self.minutes as u32,
|
||||
self.seconds as u32,
|
||||
)
|
||||
.unwrap();
|
||||
let seconds = chrono::NaiveDateTime::new(date, time)
|
||||
.signed_duration_since(chrono::NaiveDateTime::UNIX_EPOCH)
|
||||
.num_seconds() as u64;
|
||||
Self {
|
||||
seconds,
|
||||
nanoseconds: 0,
|
||||
}
|
||||
|
||||
seconds * time::TICKS_PER_SEC
|
||||
}
|
||||
}
|
||||
|
||||
pub static RTC: Rtc = Rtc::new();
|
||||
|
@ -50,7 +50,7 @@ mod smp;
|
||||
mod syscall;
|
||||
|
||||
use crate::{
|
||||
arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller},
|
||||
arch::x86::peripherals::{i8253::I8253, ps2::PS2Controller, rtc::Rtc},
|
||||
device::display::linear_fb::LinearFramebuffer,
|
||||
fs::{Initrd, INITRD_DATA},
|
||||
};
|
||||
@ -388,10 +388,9 @@ impl X86_64 {
|
||||
if let Err(error) = PS2Controller::setup() {
|
||||
log::error!("PS/2 controller init error: {error:?}");
|
||||
}
|
||||
|
||||
// RTC.init_irq()?;
|
||||
|
||||
// device::register_device(&PS2);
|
||||
if let Err(error) = Rtc::setup() {
|
||||
log::error!("RTC init error: {error:?}");
|
||||
}
|
||||
|
||||
PciBusManager::setup_bus_devices()?;
|
||||
}
|
||||
|
@ -16,7 +16,11 @@ use abi::{
|
||||
process::{ExecveOptions, ProcessId},
|
||||
time::{ClockType, SystemTime},
|
||||
};
|
||||
use libk::{module, random, task::thread::Thread, time::monotonic_time};
|
||||
use libk::{
|
||||
module, random,
|
||||
task::thread::Thread,
|
||||
time::{monotonic_time, real_time},
|
||||
};
|
||||
use libk_mm::phys;
|
||||
|
||||
use crate::fs;
|
||||
@ -55,7 +59,7 @@ pub(crate) fn unmount(_options: &UnmountOptions) -> Result<(), Error> {
|
||||
|
||||
pub(crate) fn get_clock(ty: ClockType, value: &mut MaybeUninit<SystemTime>) -> Result<(), Error> {
|
||||
let time = match ty {
|
||||
ClockType::RealTime => todo!(),
|
||||
ClockType::RealTime => real_time(),
|
||||
ClockType::Monotonic => monotonic_time(),
|
||||
};
|
||||
value.write(time);
|
||||
|
Loading…
x
Reference in New Issue
Block a user